对于std::list,最基本的遍历方式可能是这样的:
list<int> l = { 0,1,2,3,4 };
for (list<int>::iterator it = l.begin(); it != l.end(); i++) {
cout << *it << endl;
}
std::list的iterator内部维护着指向内部节点的指针,begin和end函数返回对应节点的iterator。
iterator begin() noexcept
{ // return iterator for beginning of mutable sequence
return (iterator(this->_Myhead()->_Next, _STD addressof(this->_Get_data())));
}
iterator实现了对应节点的++、--,*等运算符,维护这个for循环。
_List_const_iterator operator--(int)
{ // postdecrement
_List_const_iterator _Tmp = *this;
--*this;
return (_Tmp);
}
_List_const_iterator operator++(int)
{ // postincrement
_List_const_iterator _Tmp = *this;
++*this;
return (_Tmp);
}
_NODISCARD reference operator*() const
{ // return designated value
return (this->_Ptr->_Myval);
}
所以说在这个循环过程中,我们得到的迭代器其实是维护了一个指针的中间层对象,并不是内部节点对象。
而我们使用使用c++11的范围循环就不一样了,c++11的范围循环有以下两种用法:
for (auto &it : la) { //按引用循环
it.add();
}
for (auto it : la) { //按值循环
cout << it.get() << endl;
}
按值循环的方式与std::list迭代器所提供的遍历方式大相径庭,会将list的内部节点拷贝到循环变量it中,也就是说使用按值循环的方式修改的只是个临时变量,并没有修改list的内部节点:
int main()
{
list<int> l = { 0,1 };
for (auto it : l) { //正确的写法:for (auto &it : l) {
it++;
}
for (auto it : l) { //在遍历时还会调用拷贝构造函数,增加开销
cout << it << endl;
}
getc(stdin);
return 0;
}
//Output:
//0
//1
这种范围的原理和algorithm中提供的for_each()类似:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function fn)
{
while (first!=last) {
fn (*first);
++first;
}
return fn; // or, since C++11: return move(fn);
}
for_each将内部节点的指针解引用,以右值的形式传递,如果我们不将function的参数类型变为引用,就无法修改内部节点。
int main()
{
list<int> l = { 0,1 };
for_each(l.begin(), l.end(), [](int x) -> void{
x++;
});
for (auto it : l) { cout << it << endl; } // 0 1
for_each(l.begin(), l.end(), [](int &x) -> void {
x++;
});
for (auto it : l) { cout << it << endl; } // 1 2
getc(stdin);
return 0;
}
原文链接: https://www.cnblogs.com/HadesBlog/p/12774601.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/196527
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!