对于vector,为什么选择迭代器而不是指针呢?
For a vector, why prefer an iterator over a pointer?
在Herb Sutter的When Is a Container Not a Container?
中,他展示了一个将指针放入容器的示例:
// Example 1: Is this code valid? safe? good?
//
vector<char> v;
// ...
char* p = &v[0];
// ... do something with *p ...
接着是"improvement":
// Example 1(b): An improvement
// (when it's possible)
//
vector<char> v;
// ...
vector<char>::iterator i = v.begin();
// ... do something with *i ...
但并没有真正提供一个令人信服的论点:
一般来说,使用迭代器并不是一个坏的准则的指针当你想要指向一个在容器。毕竟,迭代器在大多数情况下都是无效的次数和方法与指针相同,这也是迭代器Exist的目的是提供一种"指向"被包含对象的方法。所以,如果你有选择,更喜欢在容器中使用迭代器。
不幸的是,迭代器不能总是得到相同的效果你可以将指针放入容器中。主要有两种迭代器方法的潜在缺点,当两者都适用时,我们必须继续使用指针:
在可以使用指针的地方,不能总是方便地使用迭代器。
使用迭代器可能会产生额外的空间和性能开销,在迭代器是一个对象而不仅仅是一个秃头的情况下指针。
对于vector,迭代器只是一个RandomAccessIterator。对于所有的意图和目的,这是一个指针的薄包装。有一个实现甚至承认了这一点:
// 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.
此外,实现存储了_Iterator
类型的成员值,该成员值为pointer
或T*
。换句话说,就是一个指针。此外,这种类型的difference_type
是std::ptrdiff_t
,所定义的操作只是薄包装(即,operator++
是++_pointer
, operator*
是*_pointer
),等等。
在Sutter的实参之后,这个迭代器类与指针相比没有任何优点,只有缺点。我说的对吗?
对于向量,在非泛型代码中,你基本上是正确的。
的好处是你可以将RandomAccessIterator传递给一大堆算法,而不管迭代器迭代的是什么容器,也不管该容器是否具有连续存储(因此指针迭代器)。这是一个抽象。
(这个抽象,除其他外,允许实现将基本指针实现替换为一些更有趣的东西,比如用于调试的范围检查迭代器。)
通常认为使用迭代器是一个好习惯,除非你确实不能使用。毕竟,习惯产生一致性,一致性导致可维护性。
迭代器也具有自文档性,而指针则没有。int*
指向什么?不知道。std::vector<int>::iterator
指的是什么?Aha…
最后,它们提供了一种类型安全措施—虽然这样的迭代器可能只是指针的薄包装,但它们不需要是指针:如果迭代器是不同的类型而不是类型别名,那么您就不会意外地将迭代器传递到您不希望它去的地方,或者意外地将其设置为"NULL"。
我同意Sutter的论点和他的大多数其他论点一样有说服力,也就是说,不是很有说服力。
在可以使用指针
的地方不能总是方便地使用迭代器
这是不是的缺点之一。有时候,把指针传递到你不想让它们去的地方实在是太"方便"了。使用单独的类型有助于验证参数。
一些早期的实现对vector::iterator使用了T*
,但它导致了各种问题,比如人们不小心将一个不相关的指针传递给vector成员函数。或者将NULL赋值给迭代器
使用迭代器可能会产生额外的空间和性能开销,在迭代器是对象而不仅仅是指针的情况下。
这是在1999年写的,当时我们还认为<algorithm>
中的代码应该针对不同的容器类型进行优化。没过多久,每个人都惊讶地发现,编译器自己发现了这个问题。使用迭代器的泛型算法工作得很好!
对于std::vector,绝对没有使用迭代器代替指针的时间开销空间。您发现迭代器类只是指针的薄包装。编译器也会看到它,并生成等价的代码。
选择迭代器而不是指针的一个现实原因是,它们可以在调试构建中作为检查迭代器实现,并帮助您及早发现一些严重的问题。即:
vector<int>::iterator it; // uninitialized iterator
it++;
或
for (it = vec1.begin(); it != vec2.end(); ++it) // different containers
- std::vector::迭代器是否可以合法地作为指针
- 不明白迭代器,引用和指针失效,一个例子
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 在C++中释放内存期间,迭代器与指针有何不同
- 迭代器的指针操作问题
- 对于随机访问迭代器(矢量迭代器),迭代器C++样式指针吗?
- 专门C++使用指针值类型的通用迭代器的模板函数?
- 从 std::vector 迭代器中执行函数指针
- 使用 map<char,strring> 的迭代器返回指针 map<char,strring>*
- 迭代器是否分配内存(如指针)?
- 如何在C++中重新实现包含指针的 STL 容器的类的迭代器
- 向量<pointer>:插入(迭代器,指针)插入垃圾值
- 迭代器可以变成指针吗?
- 用于 STL 迭代器、指针和 std::nullptr_t 的模板函数
- 如果我有一个指向矢量元素的指针,而不是迭代器,如何删除它?
- 将列表 en 列表迭代器作为指针 C++ 传递
- 将unordered_map元素指向指针/迭代器
- 如何制作指针迭代器
- 如何在C++中存储对 stl 容器元素的指针/迭代器引用
- STL容器迭代器和C指针迭代器之间的区别是什么