C++11中for循环新用法容易产生的误区

对于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】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++11中for循环新用法容易产生的误区

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/344312

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午2:37
下一篇 2023年3月2日 上午2:37

相关推荐