我发现,这个C ++代码:
vector<int> a;
a.push_back(1);
a.push_back(2);
vector<int>::iterator it = a.begin();
a.push_back(4);
cout << *it;
打印一些大的随机数; 但如果添加a.push_back(3)
第三和第四线之间,将打印1.你能解释一下?
我发现,这个C ++代码:
vector<int> a;
a.push_back(1);
a.push_back(2);
vector<int>::iterator it = a.begin();
a.push_back(4);
cout << *it;
打印一些大的随机数; 但如果添加a.push_back(3)
第三和第四线之间,将打印1.你能解释一下?
用更谨慎的措辞编辑
是的,调整向量可能指向无效到载体所有迭代器。
该载体通过在内部分配,其中的数据存储阵列来实现。 当向量的增长,该阵列可能会用完的空间,当它的载体转移到该分配一个新的,更大的,阵列,复制数据,然后删除旧的阵列。
所以,你的旧迭代器,这点到旧的内存,不再有效。 如果载体是向下调整大小(由例如pop_back()
然而,使用相同的数组。 阵列不会自动小型化。
为了避免这种重新分配(和指针失效)的一种方法是调用vector::reserve()
第一,留出足够的空间,这种复制是没有必要的。 在你的情况,如果你叫a.reserve(3)
第一之前push_back()
操作,则内部数组将是足够大了push_back
的可能,而无需重新分配阵列来进行,所以你的迭代器将保持有效。
当该矢量进行重新分配向量迭代仅无效。
调用push_back(4)
是造成分配的内存块的新载体-这是什么原因导致你的迭代器变得无效。 当您还使用push_back(3)
没有重新分配用于执行push_back(4)
因此,迭代器仍然有效。
是的,这可能会改变向量的大小的任何行动可以迭代器失效。
编辑:这包括操作(例如, erase()
resize()
减少容器的大小。 erase()
并不能否定所有迭代器,但它确实无效提及任何点擦除单元(一个或多个)之后的任何迭代器。 resize()
在以下方面被定义insert()
和erase()
因此具有相同的电位。
对于迭代器失效的规则是具体到一个容器中。
现在失效可能有2个含义有一个向量:
正如你所看到的,第二个是要严格得多:
std::vector<int> myVector;
myVector.push_back(0);
myVector.push_back(1);
std::vector<int>::iterator it = myVector.begin(); // it points to 0
myVector.erase(it); // it points to 1
myVector.erase(it); // it == myVector.end()
在这种情况下,它是“有效”的,因为它总是在包容范围[开始,结束],因此可以安全地用于对myVector任何操作。 在另一方面表达式(*吧)不断变化的:首先,它返回0,1,那么它是未定义行为...
在一般情况下,人们宁愿谈论的第二个要求,无效的迭代器只是意味着(*吧)可能不会像以前那样产生相同的结果。
现在,这是说,有几种方法可以在矢量无效的迭代器(事实上,它是STL的不太稳定的结构)。
在元素的补充:
insert
。 插入元件无效指向这个当前位置的迭代器,并且由于元件的所有后续那些错开朝向矢量的末端的一个步骤。 在消除元件:
(1)一个std ::载体的内部结构为T的阵列,这是由于用于与C-程序(myVector.front()作为数组的地址使用&)的相容性和,因为它保证连续性和最小空间开销(即,由矢量自己的数据VS的空间由物体占用的量采取的空间的量)
在任何时候,你就可以知道一个向量可以有多少个对象持有使用.capacity()方法。
当你要插入的对象和载体不具备必要的能力,被触发的.reserve(为size_t)方法的调用。 该方法,如果需要的物品的数量是优于当前容量,触发重新分配 。
该载体然后分配元件的新阵列(其大小通常为2 * N + 1,其中n是当前容量),将当前阵列到新数组的元素,丢弃当前数组。
因为它丢弃当前阵列,你的迭代器被无效作为向量迭代器通常简单的指针(对于效率)。
需要注意的是,如果迭代器是为实现:到矢量+计数的参考,并取消引用竟是*(&m_vector.front()+ n)的重新分配将不会使它们无效......但他们是效率较低。
(2)收缩以适应:警告,这触发了对元素的副本和无效迭代器。
// myVector has 10 elements, but myVector.capacity() == 1000
myVector.swap(std::vector<int>(myVector));
它首先创建的临时载体,如需要(以取决于库最小),这将仅分配尽可能多的内存,并复制myVector的元素。 然后交换操作交换从myVector缓冲器和该副本,并且因此myVector现在hols用的必要的最小内存量的缓冲器。 在操作结束时,临时被破坏和存储其持有释放。
对于未来的参考,所有的STL各种这样的花絮是在SGI的网站: http://www.sgi.com/tech/stl/Vector.html
如果您需要迭代留下您添加或删除集合后有效,看看其他类型的集合,就像一个列表。
虽则做的最好的事情是确定出你从一个集合(随机访问等)想要的功能矩阵,然后挑选合适的容器。
见起点上Standard_Template_Library集装箱维基百科的文章。 如果你有现金,我强烈建议斯科特·梅耶的“有效STL:50层具体的方法来提高你的标准模板库的使用”。
由于缺乏配套环节的道歉,在这里我是新手,缺乏信誉与多个张贴此。