在我的代码中,a有一个Node对象的全局向量和一个Node指针的局部向量:
#include#include #include using namespace std; class Node { int n; public: Node(int i) : n(i); int getN() { return n; } }; vector v; int main() { vector p; v.push_back(Node(1)); p.push_back(&v[0]); printf("first node id : %d\n", (*p[0]).getN()); return 0; }
我将一个节点对象插入到全局向量中,并将该对象的指针插入到本地向量中.我上面代码的输出是:
first node id : 1
但是,如果我将主要功能更改为:
int main() { vectorp; v.push_back(Node(1)); p.push_back(&v[0]); v.push_back(Node(2)); p.push_back(&v[1]); printf("first node id : %d\n", (*p[0]).getN()); return 0; }
代码打印垃圾值:
first node id : 32390176
我无法弄清楚这个问题.vector
插入后数据结构是否会更改每个对象的引用?我怎样才能解决这个问题 ?
可能,是的.一个std::vector
时添加/可重新分配其(堆)存储push_back()
的附加元件,无效所有的指针:
迭代器[读取:指针]失效
(用于操作)
push_back
,emplace_back
...如果向量改变了容量,则所有这些[即所有迭代器都无效].如果没有,只有end()
.
如果向量的容量由于插入而没有改变,则上述失效规则不适用 - 因为向量不会不必要地重新分配存储.因此,如果您在示例中预先将矢量的容量设置为2(例如,with v.reserve(2)
),则指针将保持有效.如果你事先不知道大小,但你可以延迟第二个向量的构造(使用指针),你不必保留,你只需要插入最后一个元素后的大小.
然而,上述方法是非常不受推荐的.如果你要使向量保持不变 - 至少在你将构造和使用第二个向量的函数范围内 - 你将有一个强大的非重新分配保证.或者,如果您可以提前确定大小,则可以使用a std::array
,并且将指针用于该容器的存储更为合适:
迭代器失效
通常,数组的迭代器在数组的整个生命周期中永远不会失效.
您也可以考虑将索引存储到向量中(尽管也存在向量可能缩小,索引无效,或者您可能在中间插入元素等).
无论如何,我怀疑你可能实际上并不想做任何这样的事情,即它似乎是一个不太好的解决方案,可以用一个完全不同的方法处理问题.
PS - 如果向量具有自定义分配器,那么我写的所有内容都可能无关紧要.