背景
我有一个对象向量和一个索引(映射)到这些对象的名称(字符串)。 在我的例子中,向量只会增长(项目永远不会被删除)。
我不知道
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...
我认为答案是肯定的,因为复制省略,但我不确定。
答案 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 )