【问题标题】:Why adding to vector does not work while using iterator?为什么在使用迭代器时添加到向量不起作用?
【发布时间】:2014-03-19 13:16:32
【问题描述】:

我有两个代码示例,它们的作用完全相同。一个是在 C++03 和 C++11 中。

C++ 11

int main()
{
    vector<int> v = {1,2,3};

    int count = 0;

    for each (auto it in v)
    {
        cout << it<<endl;

        if (count == 0)
        {
            count++;
            v.push_back(4);//adding value to vector
        }
    }

    return 0;
}

C++ 03

int main()
{
    vector<int> v = {1,2,3};

    int count = 0;

    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {

        cout << *it<<endl;

        if (count == 0)
        {
            count++;
            v.push_back(4);//adding value to vector
        }
    }

    return 0;
}

这两个代码都给出了以下异常。

现在当我看到 vector::end() 实现时,

iterator end() _NOEXCEPT
{   
// return iterator for end of mutable sequence
return (iterator(this->_Mylast, this));
}

这里,内联函数显然需要_Mylast 来计算结束。因此,当我添加时,它的指针将递增到下一个位置,例如_Mylast++。为什么我会收到此异常?

谢谢。

【问题讨论】:

  • "for each, in" 不是标准的。 c++11的范围是for(类型名:集合)。

标签: c++ c++11 vector iterator c++-standard-library


【解决方案1】:

向量将其元素存储在连续的内存中。如果该内存块需要重新分配,迭代器就会失效。

如果您需要在迭代时修改向量的大小,请按索引而不是iterator 进行迭代。

另一种选择是使用具有不同迭代器行为的不同容器,例如list 将允许您在插入项目时继续迭代。

最后,(我敢这么建议吗?)如果你知道你的向量将增长到的最大大小,.reserve() 在迭代它之前。这将确保它在循环期间不会被重新分配。我不确定这种行为是否得到标准的保证(也许有人可以插话);我绝对不会这样做,考虑到按索引迭代是非常安全的。

【讨论】:

  • resize 后跟 push_back 并没有多大帮助 - 在这种情况下应该使用 atoperator[]reservepush_back 一起使用,因为它不会改变大小,只会改变容量。就个人而言,我坚持“不要修改你正在迭代的内容”的原则。
  • 如果您想保持迭代器有效,std::dequestd::vector 的一个很好的替代品。
【解决方案2】:

您的 push_back 正在使您在 for 循环中使用的迭代器无效,因为向量正在重新分配其内存,这会使向量元素的所有迭代器无效。

对此的惯用解决方案是使用insert_iterator,就像您在向量上调用std::back_insterter 得到的一样。然后你可以这样做:

#include <iostream>
#include <iterator>
#include <vector>

int main()
{
  std::vector<int> v;
  auto inserter = std::back_inserter(v);
  for(int i=0; i<100; ++i)
    inserter = i;

  for(const auto item : v)
    std::cout << item << '\n';
}

即使通过底层容器的重新分配调用,它也会确保自己的有效性。

Live demo here.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 1970-01-01
    • 2021-08-03
    • 2020-10-17
    相关资源
    最近更新 更多