简体   繁体   English

C++ 向量插入和迭代器混淆

[英]C++ Vectors insertion and iterators confusion

int main(){
    vector<int> veclist;
    veclist.push_back(90);
    veclist.push_back(80);
    veclist.push_back(70);

    vector<int>::iterator it;
    it=veclist.begin();
    veclist.insert(it,20);
    cout << *it << endl;  // prints 20 
    it++;
    veclist.insert(it,99);
    cout << *it <<endl;  // line abc : prints 0 
}

Hi, I am working with vectors and iterators in C++.嗨,我正在使用 C++ 中的向量和迭代器。 In the above code, why is "line abc" printing 0. Shouldn't it be printing 99 instead?在上面的代码中,为什么 "line abc" 打印 0。它不应该打印 99 吗? When I print all the vector elements using a for loop, 99 is also printed but why isn't line abc doing so?当我使用 for 循环打印所有矢量元素时,也会打印 99 但为什么 line abc 不这样做? I am dereferencing the iterator *it, and I expected it to hold the element 99.我正在取消对迭代器 *it 的引用,并且我希望它能够保存元素 99。

When inserting in a vector, all previous iterators are invalidated.插入向量时,所有先前的迭代器都无效。 Everything after veclist.insert(it,20) is undefined behavior. veclist.insert(it,20)之后的所有内容都是未定义的行为。

To be more precise about what happens under the hood the reason the first print works and the second doesn't is because of the allocated std::vector capacity.为了更准确地了解幕后发生的事情,第一次打印有效而第二次打印无效的原因是分配的std::vector容量。 Most implementations allocate only 2^N memory chunks.大多数实现只分配 2^N memory块。

Therefore, initial vector has capacity of 4. When you increase size from 3 to 4, all previous iterators happen to remain valid.因此,初始向量的容量为 4。当您将大小从 3 增加到 4 时,所有先前的迭代器恰好保持有效。 However, when size grows from 4 to 8, memory is copied in a new region, therefore you're accessing deleted memory.但是,当大小从 4 增长到 8 时,memory 被复制到一个新区域,因此您正在访问已删除的 memory。

To solve this, you can simply use the result of std::vector::insert , as the valid iterator pointing to the inserted element:为了解决这个问题,您可以简单地使用std::vector::insert的结果作为指向插入元素的有效迭代器:

eg例如

it = veclist.insert(it,20);

Becausestd::vector<T,Allocator>::insert causes iterator invalidation.因为std::vector<T,Allocator>::insert导致迭代器失效。

Causes reallocation if the new size() is greater than the old capacity() .如果新的size()大于旧的capacity()则导致重新分配。 If the new size() is greater than capacity() , all iterators and references are invalidated.如果新的size()大于capacity() ,则所有迭代器和引用都无效。 Otherwise, only the iterators and references before the insertion point remain valid.否则,只有插入点之前的迭代器和引用保持有效。 The past-the-end iterator is also invalidated.过去的迭代器也无效。

That means after insert 's invocation, it has been invalidated.这意味着在insert的调用之后, it已失效。 Usage of it like *it or it++ leads to UB.*itit++这样的使用会导致 UB。

You should assign it to the return value of insert , which is the iterator pointing to the inserted value.您应该将it分配给insert的返回值,它是指向插入值的迭代器。 eg例如

vector<int>::iterator it;
it=veclist.begin();
it=veclist.insert(it,20);
cout << *it << endl;  // prints 20 
it++;
it=veclist.insert(it,99);
cout << *it <<endl;   // prints 99

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM