Trong Herb Sutter When Is a Container Not a Container?
, ông cho thấy một ví dụ về việc một con trỏ vào một container:Đối với một véc tơ, tại sao lại thích một trình lặp trên một con trỏ?
// Example 1: Is this code valid? safe? good?
//
vector<char> v;
// ...
char* p = &v[0];
// ... do something with *p ...
Rồi sau nó lên với một "cải thiện":
// Example 1(b): An improvement
// (when it's possible)
//
vector<char> v;
// ...
vector<char>::iterator i = v.begin();
// ... do something with *i ...
Nhưng không thực sự cung cấp một đối số thuyết phục:
Nói chung, không phải là hướng dẫn xấu để sử dụng trình biến đổi thay vì của con trỏ khi bạn muốn trỏ t một vật nằm bên trong một hộp chứa . Sau khi tất cả, các trình vòng lặp không hợp lệ tại hầu hết các thời điểm giống nhau và cùng một cách như con trỏ, và một lý do mà các vòng lặp tồn tại là cung cấp cách "trỏ" tại một đối tượng chứa. Vì vậy, nếu bạn có lựa chọn, thích sử dụng trình vòng lặp vào vùng chứa.
Thật không may, bạn không thể luôn có được hiệu ứng tương tự với trình vòng lặp mà bạn có thể với con trỏ vào vùng chứa. Có hai chính nhược điểm tiềm năng với phương pháp lặp, và khi một trong hai chúng tôi áp dụng phải tiếp tục sử dụng con trỏ:
Bạn có thể không phải lúc nào thuận tiện sử dụng một iterator nơi bạn có thể sử dụng một con trỏ. (Xem ví dụ bên dưới.)
Sử dụng trình vòng lặp có thể phát sinh thêm không gian và chi phí hiệu năng, trong trường hợp trình lặp là đối tượng chứ không chỉ là con trỏ hói .
Trong trường hợp của một véc tơ, biến lặp chỉ là một RandomAccessIterator. Đối với tất cả các ý định và mục đích này là một wrapper mỏng trên một con trỏ. Một thực hiện thậm chí thừa nhận điều này:
// This iterator adapter is 'normal' in the sense that it does not
// change the semantics of any of the operators of its iterator
// parameter. Its primary purpose is to convert an iterator that is
// not a class, e.g. a pointer, into an iterator that is a class.
// The _Container parameter exists solely so that different containers
// using this template can instantiate different types, even if the
// _Iterator parameter is the same.
Bên cạnh đó, việc thực hiện lưu trữ một giá trị thành viên của loại _Iterator
, đó là pointer
hoặc T*
. Nói cách khác, chỉ cần một con trỏ. Hơn nữa, difference_type
cho loại như vậy là std::ptrdiff_t
và các hoạt động được xác định chỉ là trình bao bọc mỏng (tức là, operator++
là ++_pointer
, operator*
là *_pointer
) v.v.
Theo đối số của Sutter, lớp trình lặp này không mang lại lợi ích nào so với con trỏ, chỉ có nhược điểm. Tôi có đúng không?
Không có 'giới hạn', điều này có ý nghĩa rất ít khi nói hiệu suất trên một trong hai. – user3528438
Có vẻ như vấn đề là tự lừa dối bạn bằng cách gọi các trình bao bọc giấy mỏng của các trình vòng lặp con trỏ. Nếu bạn gọi một con trỏ là một con trỏ và để lại thuật ngữ vòng lặp cho một thứ mà chỉ bao giờ trỏ đến một trong các thành viên của một thùng chứa, vv thì nó trở thành một sự lựa chọn thực sự giữa một trình lặp với các biện pháp bảo vệ và một con trỏ không có. – Paddy3118