我目前有一个类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 *>
}
答案 0 :(得分:3)
vector
将其元素存储在数组中。数组是一个连续的元素序列。
如果您有vector
个元素a, b, c, d
并删除元素b
,则元素c
和d
会向下移动到数组中的一个索引填充已删除元素创建的洞,留下包含a, c, d
的数组。
指针在移动时不跟随vector
中的元素“跟随”。如果你有一个“指向c
”的指针,那么指针真正指向“数组中索引为2
的元素”。从数组中删除b
时,“索引为2
的元素”为d
,而不是c
。
如果您希望某个对象拥有一个永不改变的固定地址,您应该自己动态分配它并使用智能指针(如unique_ptr
或shared_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
中对象的指针,因为它很危险。