指针实际上并没有指向对象本身?

时间:2011-08-21 01:44:31

标签: c++ pointers vector

我目前有一个类Foo的向量和另一个指针向量,指向向量中Foo的子集。我目前有一个函数可以从vector<Foo *>中选择一些指针,并从实际包含它们的vector<Foo>中删除它们。因此,一开始,这两个向量看起来像这样:

//Foo classes in vector<Foo>
a
b
c
d

//Foo pointers in vector<Foo *>
*a
*b
*c
*d

但是,我发现删除Foo后,说b,它们看起来像这样:

//Foo classes in vector<Foo>
a
c
d

//Foo pointers in vector<Foo *>
*a
*c
*d
*d

c中删除vector<Foo *>之后,c中指向b的指针是如何指向vector<Foo>的?有什么方法可以解决这个问题吗?

(据我所知,如果我删除b,原来指向b的指针将是悬空的;但是,因为我无意中删除了b之后,我认为这没关系,我可以使用指向c

的指针转到下一个索引

修改

根据要求,填充指针向量的代码:

for(int i = 0; i < a.size(); i++) //a is the vector<Foo>
{
    Foo * thisFoo = &a[i];
    if(someConditionMet)
        b.push_back(thisFoo); //b is the vector<Foo *>
}

3 个答案:

答案 0 :(得分:3)

vector将其元素存储在数组中。数组是一个连续的元素序列。

如果您有vector个元素a, b, c, d并删除元素b,则元素cd会向下移动到数组中的一个索引填充已删除元素创建的洞,留下包含a, c, d的数组。

指针在移动时不跟随vector中的元素“跟随”。如果你有一个“指向c”的指针,那么指针真正指向“数组中索引为2的元素”。从数组中删除b时,“索引为2的元素”为d,而不是c

如果您希望某个对象拥有一个永不改变的固定地址,您应该自己动态分配它并使用智能指针(如unique_ptrshared_ptr)跟踪它。

答案 1 :(得分:2)

如果你想完成这样的事情,你将无法使用vector<foo>来实际掌控foo个对象本身。在我看来,foo*的子向量必须实际上指向vector<foo>负责的内存。 (因此,这就是为什么你仍然在末尾看到指向d的附加指针,并且你仍然有4的长度。)

在我看来,你真正想要做的是使用两个vector<foo*>,并手动创建存储在第一个中的对象,而不是让向量本身负责对象。然后让你的第二个vector<foo*>只是复制指向你创建的对象的指针。这样,当您从第一个vector<foo*>中删除某个项目时,它只会删除其指针副本,而您的第二个vector<foo*>将不受影响。

在没有涉及向量的情况下想一想:

// create the initial storage for all the foo
foo* fooarray = new foo[foo_count];

// create all the foos for the array
for (int i=0; i < foo_count; ++i)
   fooarray = new foo();

// get a pointer to a subset of foo 
foo* foo_subset_pointer = &fooarray[10];

// make a list of a subset of the fooarray pointers
foo* foo_subset_list = new foo[10];
for (int i=0; i < 10; ++i)
    foo_subset_list = fooarray[i];

所以,现在当你从fooarray中删除一个元素时:

// remove fooarray[3]
delete fooarray[3]; 
for (int i=4; i < 20; ++i)
   fooarray[i-1] = fooarray[i];

foo_subset_pointer将删除其原始项目3,因为它只是指向现有数组的指针。 (如果您访问foo_subset_pointer[19],它仍然会指向与foo_subset_pointer[18]相同的内容,因为这些项目未归零......)

但更糟糕的是,foo_subset_list[3]仍指向原始位置:但它已被删除,因为它已被删除!这就是为什么当您处理要保留的子集时,您不希望向量负责列表项。

相反,听起来你希望你的第一个向量只去除项目(上面的for循环),而不是delete。在这种情况下,它会使foo_subset_list[3]保持不变,仍然指向有效的foo。另外一个困难是你现在必须确保在将来某个时候做delete foo_subset_list[3];。但它允许你拥有似乎是你想要的行为。

答案 2 :(得分:1)

当移除vector中的对象时,vector中较大索引处的所有对象都向下移动以关闭“洞”。指向任何这些对象的指针都将变为无效。检测情况的唯一方法是不要首先进入这种情况 - 不要存储非const vector中对象的指针,因为它很危险。