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

前端 未结 3 2018
故里飘歌
故里飘歌 2020-12-07 05:15

Answering How to self-copy a vector? has got me a bit confused about iterator invalidation. Some literature says \"if you use insert, push_back, etc. consider all iterators

3条回答
  •  失恋的感觉
    2020-12-07 05:52

    Iterators should not be invalidated mid function. The idea that memory may be relocated doesn't hold up, because you cannot use realloc on objects with non-trivial constructors. Even if construction was a not an issue, it would still have to copy the initial sequence twice in the worst case, negating any benefits in the average case.

    Point being, it doesn't make sense to implement it that way; an alloc, copy, free is almost certainly done, regardless of what the standard says.

    This is safe because v.begin() and v.end() are always current.

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

    This is not.

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

    However, self insertion can be wonky. Try the following under GCC. The self insertion gives an incorrect result only if enough memory is available (not sure if this is a 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 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::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;
    }
    

    Note: The above opinion applies to vector specifically, not containers in general. Also, the suggestion that the above behavior may be a bug has nothing to do with the standard, rather the ease of implementing a robust self insertion for vector.

提交回复
热议问题