2013-04-09 37 views
17

Có một loạt dựa trên vòng lặp for với cú pháp:Phạm vi dựa trên vòng lặp trên mảng động?

for(auto& i : array) 

Nó hoạt động với mảng liên tục nhưng không phải với con trỏ những động dựa, như

int *array = new int[size]; 
for(auto& i : array) 
    cout<< i << endl; 

Nó cho lỗi và cảnh báo về sự thất bại của thay thế, ví dụ:

Error] C:\Users\Siegfred\Documents\C-Free\Temp\Untitled2.cpp:16:16: error: no matching function for call to 'begin(int*&)'

Làm cách nào để sử dụng cú pháp mới này với mảng động?

+2

gì các lỗi có nói gì không? Ít nhất bài ** one ** lỗi – Default

+1

nó được gọi là phạm vi dựa trên vòng lặp và SO và Google có tấn ví dụ – stijn

+0

[Lỗi] C: \ Users \ Siegfred \ Documents \ C-Free \ Temp \ Untitled2.cpp: 16: 16: lỗi: không có chức năng phù hợp cho cuộc gọi đến 'bắt đầu (int * &)' –

Trả lời

19

Để tận dụng các phạm vi có trụ sở tại vòng bạn phải cung cấp một trong hai begin()end() hàm thành viên hoặc quá tải không thành viên begin()end() chức năng. Trong trường hợp sau, bạn có thể quấn phạm vi của bạn trong một std::pair và quá tải begin()end() cho những:

namespace std { 
     template <typename T> T* begin(std::pair<T*, T*> const& p) 
     { return p.first; } 
     template <typename T> T* end(std::pair<T*, T*> const& p) 
     { return p.second; } 
    } 

Bây giờ bạn có thể sử dụng cho vòng lặp như thế này:

for (auto&& i : std::make_pair(array, array + size)) 
     cout << i << endl; 

Lưu ý, rằng các hàm không phải là thành viên begin()end() phải được quá tải trong không gian tên std tại đây, bởi vì pair cũng nằm trong không gian tên std. Nếu bạn không muốn giả mạo không gian tên chuẩn, bạn có thể chỉ cần tạo một lớp cặp nhỏ của riêng bạn và quá tải begin()end() trong không gian tên của bạn.

Hoặc, tạo một wrapper mỏng xung quanh mảng cấp phát động của bạn và cung cấp begin()end() thành viên chức năng:

template <typename T> 
    struct wrapped_array { 
     wrapped_array(T* first, T* last) : begin_ {first}, end_ {last} {} 
     wrapped_array(T* first, std::ptrdiff_t size) 
      : wrapped_array {first, first + size} {} 

     T* begin() const noexcept { return begin_; } 
     T* end() const noexcept { return end_; } 

     T* begin_; 
     T* end_; 
    }; 

    template <typename T> 
    wrapped_array<T> wrap_array(T* first, std::ptrdiff_t size) noexcept 
    { return {first, size}; } 

Và trang web cuộc gọi của bạn trông như thế này:

for (auto&& i : wrap_array(array, size)) 
     std::cout << i << std::endl; 

Example

16

Bạn không thể sử dụng phạm vi cho vòng lặp với mảng được phân bổ động, vì trình biên dịch không thể suy ra bắt đầu và kết thúc mảng này. Bạn nên luôn sử dụng các vùng chứa thay vì nó, ví dụ: std::vector.

std::vector<int> v(size); 
for(const auto& elem: v) 
    // do something 
+0

@Zoidberg, đã chỉnh sửa, cảm ơn :) – soon

+1

tốt, nó đã hoạt động! tôi không bao giờ biết C++ sẽ được loại an toàn, tôi đến từ C, do đó, một đã được sử dụng để thao tác mảng năng động và liên tục trong cùng một cách. –

+0

@MauriceRodriguez Vâng, * C * có sự khác biệt này giữa mảng và con trỏ theo cùng một cách. Ví dụ 'sizeof (mảng)' trả về những thứ hoàn toàn khác nhau trong * C *, cũng vậy, phụ thuộc vào nếu nó là 'int * array = malloc (N * sizeof (int));' hoặc 'int array [N];'. Vì vậy, nó chỉ là vì * C * làm cho nó dễ dàng hơn cho bạn * không chính xác * bỏ qua sự khác biệt này, không phải là sự khác biệt này không có ở đó. –

8

Bạn không thể thực hiện vòng lặp dựa trên dải ô được phân bổ động vì tất cả những gì bạn có là con trỏ đến phần tử đầu tiên. Không có thông tin liên quan đến kích thước của nó mà trình biên dịch có thể sử dụng để thực hiện vòng lặp. C++ giải pháp thành ngữ sẽ được thay thế các mảng cấp phát động bởi một std::vector:

std::vector<int> arr(size); 
for(const auto& i : arr) 
    std::cout<< i << std::endl; 

Một loạt dựa cho vòng lặp không làm việc cho std::array đối tượng. Bạn cần phải nhìn qua các trường hợp mảng (arr), không phải là loại (array):

std::array<int,10> arr; 
for(const auto& i : arr) 
    std::cout<< i << std::endl; 
+1

Bạn có thể đã xếp dãy '' trên một mảng tự động được cấp phát trống, không cần thêm lớp trình bao bọc chỉ cho điều này. 'int a [] {1, 2, 3}; cho (tự động nó: a) std :: cout << it << ''; 'Mỗi số phần tử tạo ra một kiểu riêng biệt mà' kết thúc' có thể được suy ra khi biên dịch vòng lặp. –

-1

Xem trang này http://www.codeproject.com/Articles/570638/Ten-Cplusplus11-Features-Every-Cplusplus-Developer và tìm chương "phi thành viên bắt đầu() và kết thúc()". Đây có thể là những gì bạn muốn đạt được.

+0

Bạn có thể liên kết trực tiếp đến chương đó bằng lệnh neo #beginend, vì vậy [như thế này] (http://www.codeproject.com/Articles/570638/Ten-Cplusplus11-Features-Every-Cplusplus-Developer#beginend). – Default

+2

Bạn nên cố gắng thêm nội dung của những gì bạn muốn người dùng đọc, vì [liên kết chỉ có câu trả lời có phần không được khuyến khích] (http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain -links-anywhere-really-good-answers). – Default

+0

"Điều này có thể là những gì bạn muốn đạt được." Không, nó không thể. Nó sẽ yêu cầu một số cách để suy ra kích thước/phần tử cuối cùng cho một mảng động chỉ cho một thể hiện kiểu generic của nó, điều này là không thể ... và nên rõ ràng từ thực tế là các hàm như vậy chưa được cung cấp, cho điều này lý do chính xác. –

Các vấn đề liên quan