2017-09-11 24 views
7

I understand (at least I think I do) con trỏ đó có thể được sử dụng làm trình lặp STL ngẫu nhiên.Xóa vector STL qua con trỏ

Tại sao mã sau không biên dịch trừ khi tôi truyền con trỏ tới trình lặp?

vector<int> v{1, 2, 3}; 
v.erase(&v[0]); 
+12

Tại sao bạn nghĩ con trỏ đến phần tử giống với một trình lặp ('std :: vector :: iterator')? – NathanOliver

+1

Lỗi nào bạn nhận được? –

+6

Trong khi trình vòng lặp có thể được triển khai bằng con trỏ, con trỏ không tự động là trình lặp. –

Trả lời

12

Bạn có thể vượt qua con trỏ để thuật toán như std::sort, std::find, hoặc std::copy. Đây là các mẫu được cấu hình cho bất kỳ thứ gì hoạt động như một trình lặp thích hợp.

Điều này không có nghĩa là các trình vòng lặp khác nhau nhất thiết phải chuyển đổi với nhau.

Phương thức erase của vùng chứa std::vector<int> chỉ có thể hoạt động với trình vòng lặp tới các phần tử của cùng một vectơ. Như đã chỉ ra điều này có thể được thực hiện như một con trỏ, nhưng nó thường không phải là, vì những lý do đã nêu ở đây: C++ std::vector<>::iterator is not a pointer, why?

Cân nhắc std::find:

template< class InputIt, class T > 
InputIt find(InputIt first, InputIt last, const T& value); 

Đây InputIt là một tham số mẫu. Mẫu std::find sẽ hoạt động với bất kỳ loại trình lặp nào đáp ứng các yêu cầu của một input iterator và có operator* trả về một cái gì đó có thể được so sánh với loại T. Con trỏ hoạt động tốt ở đây. Như Fire Lancer đã chỉ ra chính xác trong một nhận xét, cả hai số firstlast phải thuộc loại InputIt.

Bây giờ so sánh này để std::vector::erase:

iterator erase(const_iterator pos); 

này có một const_iterator, đó là một trong những typedefs của lớp std::vector. Đây là một loại biến lặp cụ thể, không phải là tham số mẫu.

+1

Cũng đi qua ** cặp ** của con trỏ đến các thuật toán đó là một loại truy cập ngẫu nhiên có hiệu quả. Tuy nhiên, bạn vẫn không thể vượt qua một con trỏ và một iterator vector như là một cặp "" cho những người, ngay cả khi con trỏ bên trong vector. –

1

Định nghĩa của vector.erase(...)

iterator erase(const_iterator pos);

Các const iterator là một lớp học của riêng mình. Vì vậy, nếu có một chuyển đổi của một con trỏ đơn giản để lớp này, sau đó điều này có thể được thực hiện. Nhưng tôi không nghĩ là có gì cả.

Nhưng có một điều là sử dụng nó ở một nơi mà một trình lặp được mong đợi và một thứ khác là sử dụng trong các thuật toán.

Trường hợp yêu cầu iterator, chỉ có thể sử dụng trình lặp.

Trong thuật toán, không thể mong đợi iterator. Chỉ một đối tượng mà một số Concept của số iterator được satisified (thường là một số beginend trả về bộ lặp/con trỏ yêu cầu).

+0

Thuật toán mong đợi trình lặp, không phải "đối tượng mà bắt đầu/kết thúc ..." bất cứ điều gì. – juanchopanza

+1

Thuật toán sử dụng các mẫu - các tham số không phải là các kiểu cụ thể của '' 'iterator'''. Bạn có thể truyền bất kỳ đối tượng nào thỏa mãn khái niệm '' 'iterator''' thành các hàm. –

+0

Điểm của tôi chính xác. Cảm ơn bạn đã sửa. – juanchopanza

0

Mặc dù con trỏ là trình lặp, chúng không giống nhau loạivector trình lặp (ít nhất chúng không nhất thiết phải là).

Bạn có thể chuyển đổi con trỏ thành phần tử của vectơ thành một trình lặp bằng cách sử dụng vòng lặp số và con trỏ như thế này.

std::vector<int> v{1, 2, 3}; 

int* p = &v[0]; // a pointer 

auto v_iter = v.begin() + std::distance(v.data(), p); // an equivalent vector::iterator 

v.erase(v_iter); 

này chỉ làm việc với container tiếp giáp như std::vector hoặc std::array.

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