如何使用STL正确跟踪地址?

时间:2013-11-28 11:36:09

标签: c++ memory-management c++11 stl

背景

我有一个对象向量和一个索引(映射)到这些对象的名称(字符串)。 在我的例子中,向量只会增长(项目永远不会被删除)。

我不知道

struct Foo { };
std::vector<Foo>            v;
std::map<std::string,Foo*>  m;   // addresses are &v[0], &v[1], etc...

因为当我将项目添加到v时,如果m被重新分配,v中的旧映射可能会失效。

问题

如果我通过std::unique_ptr<>添加额外的抽象级别,m是否可以v重新分配?

struct Foo { };
std::vector<std::unique_ptr<Foo>>  v;
std::map<std::string,Foo*>         m;   // addresses are v[0].get(), v[1].get(), etc...

我认为答案是肯定的,因为复制省略,但我不确定。

1 个答案:

答案 0 :(得分:1)

简短回答:是的,但它与copy elision

无关

一些细节

在第一种情况下,向量的已分配内存是Foo的连续数组。 正如您所暗示的那样,在生成向量时,如果当前数组的容量不够大,则会分配一个新数组,并且索引中的指针仍然指向旧地址。

// let x be sizeof(Foo)

Adresses       10     10+x   10+2x
Type        [  Foo |  Foo |  Foo ]

重新分配

Adresses       30     30+x   30+2x   30+3x
Type        [  Foo |  Foo |  Foo  |  Foo ]

如您所见,地址10处不再找到第一个Foo对象。

第二种方法

使用第二种方法,您不是通过向量中的值存储Foo,而是通过指针存储。假设您在免费存储中正确地为指向的Foo对象分配内存,则此对象不需要移动。 当Vector增长并需要重新分配时,它会为你的Foo对象分配一个新的(唯一)指针数组,unique_ptr的地址会改变(如果你想要你的Foo **),对象保留在完全相同的地址和以前一样(Foo *是一样的)。

// let y be sizeof(Foo*)

Adresses       10     10+y   10+2y  .. 50   ..  60  ..  90          
Type        [  Foo* | Foo* | Foo* ]   [Foo]    [Foo]   [Foo]
Value       (  50     60     90   )

重新分配

Adresses       30     30+y   30+2y  30+3y   .. 50   ..  60  ..  90  ..  110          
Type        [  Foo* | Foo* | Foo*  | Foo* ]   [Foo]    [Foo]   [Foo]   [Foo]
Value       (  50     60     90      110   )