2013-11-28 35 views
1

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

我有对象的矢量和由名称(字符串)的索引(地图)到那些对象。 在我的情况下,矢量只增长(项目永远不会被删除)。

我不知道这个

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

因为我添加项目到v,老映射在m可能成为无效应该v被realloc'ed。

问题

如果我通过std::unique_ptr<>添加额外的抽象级别,将m是确定应v被realloc'ed?

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

我认为答案是肯定的,由于复制elision,但我不知道。

+1

,除非你真的需要在载体中的项目将被存储在一个连续的内存区域,你可能想看看['标准:: deque'(HTTP: //en.cppreference.com/w/cpp/container/deque)。指向元素deque(或迭代器)的指针永远不会失效(除非元素当然被移除)。 –

+0

'std :: map '其中int是索引到vector中。那么重新分配没有问题。 – john

+0

@john是的,我认为索引/间接 - 我只是想知道上述解决方案是否会解决问题 – kfmfe04

回答

1

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

一些细节

在第一种情况下,对于矢量分配的内存是富的连续阵列。 正如你所暗示的那样,当增长向量时,如果当前数组的容量不够大,将分配一个新数组,并且索引中的指针仍指向旧地址。

// 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 ] 

正如你所看到的,第一Foo对象没有再被在地址10

第二条本办法

你的第二个方法发现,你不是通过向量中的值存储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 )