简体   繁体   English

使用地图 <int, Foo> 代替矢量 <Foo> 避免指针失效

[英]Using map<int, Foo> instead of vector<Foo> to avoid pointer invalidation

Say I have a class Foo , and a container vector<Foo> Foos . 假设我有一个Foo类和一个容器vector<Foo> Foos The algorithms I use rely heavily on pointers to the elements of Foos , and I also need to add Foo s dynamically and to access elements of the container. 我使用的算法在很大程度上依赖于指向Foos元素的指针,并且我还需要动态添加Foo并访问容器的元素。 The problem is that if I add too many elements to the vector, it may need to reallocate the elements, hence invalidating all the pointers to these elements. 问题是,如果我向向量添加太多元素,则可能需要重新分配元素,从而使指向这些元素的所有指针无效。 Would it make sense then to use something like map<int, Foo> instead of vector<Foo> ? 然后使用map<int, Foo>代替vector<Foo>有意义吗?

std::deque has similar performance (and random-access) to vector, but does not invalidate pointers upon insertion. std::deque具有与vector类似的性能(和随机访问),但不会在插入时使指针无效。

It does invalidate pointers on deletion, though. 但是,它确实会使删除指针无效。

我将使用std::vector<std::shared_ptr<Foo>> ,所以我仍然有一个向量,无论它们在向量中的位置如何,我仍然需要任何有效的指针。

This answer focuses on how to prevent pointer invalidation from happening, while still sticking to std::vector . 这个答案集中于如何防止指针失效的发生,同时仍然坚持std::vector

Preallocating 预分配

If you know beforehand the maximum number of Foo objects that the vector can contain, you can simply reallocate the vector's buffer with the std::vector::reserve() member function. 如果事先知道向量可以包含的Foo对象的最大数量,则可以使用std::vector::reserve()成员函数简单地重新分配向量的缓冲区。 This way, a reallocation of the objects won't happen and therefore the pointers to the Foo objects won't be invalidated. 这样,就不会发生对象的重新分配,因此指向Foo对象的指针不会失效。

Using a vector of pointers 使用指针向量

Alternatively, you can use std::vector<std::unique_ptr<Foo>> instead of std::vector<Foo> . 或者,您可以使用std::vector<std::unique_ptr<Foo>>代替std::vector<Foo> This way, even if the vector reallocates its elements, the address of the pointed Foo objects won't change since it will be the std:unique_ptr<Foo> objects the ones that will be reallocated, not the Foo objects. 这样,即使向量重新分配了其元素,指向的Foo对象的地址也不会更改,因为它将是将要重新分配的std:unique_ptr<Foo>对象,而不是Foo对象。 Therefore, the pointers to the Foo objects will still be valid. 因此,指向Foo对象的指针仍然有效。


The latter approach introduces an additional layer of indirection, and it is, therefore, less efficient than the former one. 后一种方法引入了附加的间接层,因此,效率比前一种低。

You have four possibilities: 您有四种可能性:

  • You use a non-invalidating container. 您使用非无效容器。 That's your suggestion. 那是你的建议。

  • You reserve sufficient space in the vector beforehand ( El Professor's answer ). 您事先在向量中保留了足够的空间( El教授的答案 )。 This only works when you know the maximum amount of Foo s in advance. 仅当您事先知道Foo的最大数量时,此方法才有效。

  • You use a vector of (smart) pointers ( Michael Chourdakis' answer ). 您使用(智能)指针的向量( Michael Chourdakis的答案 )。 This works as long as you do not need to use the pointers as iterators. 只要您不需要将指针用作迭代器,此方法就起作用。

  • You make no change to your vector<Foo> , but instead of pointers, you make your algorithm work with indices. 您无需对vector<Foo>进行任何更改,但可以使索引使用算法来代替指针。 This allows you to look at the element before and after (after checking the vector bounds), and the indices won't be invalidated by reallocations. 这使您可以查看元素的前后(检查向量边界之后),并且索引不会因重新分配而无效。

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

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