是否性病::矢量::插入()如果向量有足够的空间(通过储备创造)迭代器失效?(Does std::v

2019-07-19 18:17发布

在回答如何进行自我复制的载体? 已经让我有点困惑迭代器失效。 有些文献说,“如果你使用INSERT,的push_back等考虑所有迭代器无效”。 那是明显的,它可能会导致其成长无效迭代器的矢量。 什么是特殊情况下,我知道那里将是足够的空间?

第一次尝试:

myvec.reserve(myvec.size()*3);  //does this protect me from iterator invalidation?
vector<string>::iterator it = myvec.end();    
myvec.insert(myvec.end(), myvec.begin(), it);
myvec.insert(myvec.end(), myvec.begin(), it);

经过一些优秀的答案,第二次尝试:

auto size = myvec.size();
myvec.reserve(size*3);  //does this protect me from iterator invalidation?  
myvec.insert(myvec.end(), myvec.begin(), myvec.begin()+size);
myvec.insert(myvec.end(), myvec.begin(), myvec.begin()+size);

经过优良的答案第三次尝试:

auto size = myvec.size();
myvec.reserve(size*3);  //does this protect me from iterator invalidation?  
back_insert_iterator< vector<string> > back_it (myvec);
copy (myvec.begin(),myvec.begin()+size,back_it);
copy (myvec.begin(),myvec.begin()+size,back_it);

本报价由约祖蒂斯‘C ++标准库参考’:

插入或删除元素无效引用以下元素引用,指针和迭代器。 如果插入引起的重新分配,这一切无效引用,迭代器和指针。

表明我的代码是安全的和定义的行为。 有没有在这个担保标准的一个通道?

Answer 1:

过去最末端迭代器总是有点特别。 我会小心。 标准说,这(23.3.6.5):

如果没有重新分配情况,所有的迭代器和插入点之前引用保持有效。

这里的关键是“插入点之前”。 因为你原来it不是将插入点之前(因为它插入点),我不会行其上剩余的有效。



Answer 2:

虽然这是事实,插入到载体中不会造成再分配只要容量不被超过,并且不会失效迭代以将插入点之前的元素(其可以说是的情况下end()作为@KerrekSB指出出),表C ++ 11标准的100(段落23.2.3)指定为以下前提 a.insert(p,i,j)函数序列容器:

[...]前:i和j不是迭代器成。 [...]

在你的情况,他们显然是,这让我觉得程序未定义行为。



Answer 3:

迭代器不应该是无效的中期功能。 有观点认为,存储可以被重新定位不成立了,因为你不能使用realloc与非平凡的构造函数的对象。 即使建设是不是一个问题,但它仍然不得不在最坏的​​情况下两次复制初始序列,在平均情况下否定任何好处。

点是,它没有任何意义实施这样说。 在alloccopyfree几乎可以肯定是做了,不管标准说什么。

因为这是安全的v.begin()v.end()总是电流。

v.insert(v.end(), v.begin(), v.end());
v.insert(v.end(), v.begin(), v.end());

这不是。

vector<foo>::iterator i = v.begin();
vector<foo>::iterator j = v.end();
v.insert(v.end(), i, j);
v.insert(v.end(), i, j);

然而,自我插入可以靠不住的。 尝试下GCC以下。 自插入给出了如果有足够的内存可用不正确的结果(不知道这是一个bug)。

int main()
{
    int position = 1, first = 2, last = 3;
    // enforce error condition.
    assert(position < first);
    int size = 8;
    // sanity check.
    assert(first < last && last <= size);

    std::vector<int> right, wrong;
    // force resize during insertion.
    right.reserve(size);
    // avoid resize during insertion.
    wrong.reserve(size + (last - first));

    for ( int i = 0; i < size; i++ )
     {
       right.push_back(i);
       wrong.push_back(i);
     }

    std::vector<int>::iterator i;
    i = right.begin();
    right.insert(i + position, i + first, i + last);
    i = wrong.begin();
    wrong.insert(i + position, i + first, i + last);

    assert(right == wrong);
    return 0;
}

注:上述意见适用于vector具体而言,不是一般的容器。 同样,上述行为可能是一个错误的建议无关的标准,而执行难度为一个强大的自我插入的vector



文章来源: Does std::vector::insert() invalidate iterators if the vector has enough room (created through reserve)?