const_iterator和iterator之间有什么区别?

153

这两种类型在STL内部实现上有什么区别? 就性能而言,它们之间有什么不同? 我猜当我们以“只读方式”遍历vector时,我们更喜欢使用const_iterator,对吗?

谢谢。

3个回答

155

性能没有区别。

const_iterator 是一个指向常量值的迭代器(就像const T*指针);对其进行解引用将返回对常量值(const T&)的引用,并防止修改所引用的值:它强制实现了const正确性

当你有一个容器的常量引用时,你只能获得const_iterator

编辑:我提到“const_iterator返回常量指针”,这是不准确的,感谢Brandon指出。

编辑:对于COW对象,获取非常量迭代器(或对其进行解引用)可能会触发复制。(一些已过时且现在被禁止的std::string实现使用COW。)


30
正确的翻译是:除了 (const T*) 不是常量指针,它是指向常量的指针。 - Brandon
6
迭代器常量化可能会影响性能。将迭代器声明为常量是向编译器提供的一条提示,使其可以假设底层对象不会通过迭代器操作而被改变。编译器可以使用这样的提示来实现更具体的优化。 - WiSaGaN
3
@WiSaGaN:我认为这不是真的。底层对象很可能会通过其他方式改变,而我不认为编译器可以假定底层对象不会改变(http://www.gotw.ca/gotw/081.htm)。 - ysdx
1
@ysdx 他们确实这样做。他们不依赖于用C++编写的“const”,而是依赖于自己的“着色”标签。 - v.oddou
1
是的,clang源代码中有llvm/IR/Attributes.h Attribute::AttrKind::ReadOnly这个标记,注释是“函数只从内存中读取”。有许多这样的着色标记,它们甚至会按层次结构合并和组合(即它们具有调用图感知能力)。编译器能够了解许多东西,例如如果一个函数没有副作用... 这里有一份关于优化器传递的好文档http://llvm.org/docs/Passes.html,它可以快速概述编译器正在做的事情。 - v.oddou
显示剩余4条评论

52

在性能方面没有区别。使用const_iterator而不是iterator的唯一目的是管理各自迭代器运行的容器的可访问性。您可以通过以下示例更清楚地了解:

std::vector<int> integers{ 3, 4, 56, 6, 778 };

如果我们要读写容器的成员,我们将使用迭代器:

for( std::vector<int>::iterator it = integers.begin() ; it != integers.end() ; ++it )
       {*it = 4;  std::cout << *it << std::endl; }
如果我们只想读取容器 integers 的成员,您可能希望使用 const_iterator,它不允许写入或修改容器的成员。
for( std::vector<int>::const_iterator it = integers.begin() ; it != integers.end() ; ++it )
       { cout << *it << endl; }

注意:如果您尝试在第二种情况下使用*it修改内容,会出现错误,因为它是只读的。


10

如果你有一个列表a,然后按照以下语句执行

list<int>::iterator it; // declare an iterator
    list<int>::const_iterator cit; // declare an const iterator 
    it=a.begin();
    cit=a.begin();

你可以使用"it"而不是"cit"来更改列表中元素的内容, 也就是说,你可以使用"cit"来读取元素的内容,但不能用它来更新元素。

*it=*it+1;//returns no error
    *cit=*cit+1;//this will return error

1
我认为 OP 最关心的是 性能差异,并且非常清楚 const_iterator 的只读特性。 - mkl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接