2010-10-05 90 views
1

说我有这样的:std :: vector指针是否可靠?

Object *myObject; 
std::vector<Object> objects(99); 

.... 
myObject = &objects[4]; 

难道是安全的假设,myObject的的指针永远是有效的,不管对象有多大[]得到,如果我删除一些,只要我不抹去( )myObject指向的实际对象?或者它的工作方式不同?如果上述不起作用,我还能如何实现这一目标?这是因为在我的设计中,我想要一个孩子有一个指向其父母的指针,当孩子被添加时父指定父指针,但父母在std :: vector中,我需要随机访问。在我的情况下,std :: list会更好吗?

谢谢

+0

你的意思是'std :: vector objects [99];',对吧? – 2010-10-05 22:41:01

+0

不,我暗示构造函数初始化99只是为了有一些工作:p – jmasterx 2010-10-05 22:43:27

回答

2

如果矢量填补了其分配的空间,您尝试插入更多的,它需要重新分配它的存储,这将涉及在对象复制和摧毁旧的存储,这将无效指针你保持着 - 不,这不够好。

std :: list可以正常工作,因为它不依赖连续存储,但是失去了快速随机访问的能力。或者,您可以在您的集合中存储指向您的对象的指针,在这种情况下,您可以取出该元素,并且指针将保持有效,直到您在代码中释放该内存为止 - 但是您需要在某个点处理它。

另一种选择可能是deque;虽然deque迭代器被push_back无效,但直接引用元素(如您在此使用的指针)仍然有效。

+0

由于我没有做随机插入,会出队最好吗? – jmasterx 2010-10-05 22:49:25

+0

@Milo:这取决于你的要求。如果你需要删除东西,那么只要你只删除第一个或最后一个元素就可以了,但是如果你删除了集合中间的元素是不行的 - 如果你这样做,你需要别的东西。如果这不是问题,我会去一个deque,因为你在O(1)中得到随机访问,而对于一个std :: list,它是O(n)。 – 2010-10-05 22:59:43

+0

如果这不符合你的需求,但你仍然想要更高效的访问,另一个选项*可能是std :: map或std :: set,尽管它与当前的解决方案完全不同:插入或擦除从任何一个不会使迭代器或指针无效。不知道任何有关对象的信息,很难说这对您是否合适。 – 2010-10-05 23:06:21

5

不,这是绝对不安全的假设。

该标准解释了什么会使标准容器上的迭代器无效;任何时候一个矢量迭代器失效,一个指向它的指针也是。在实践中,这意味着当矢量调整大小时(包括隐式地调用push_back()时),任何指向它的迭代器都将失效,就像指针一样。同样,调用erase()会使已擦除项目后的指针无效,因为它们都必须向上移动以填充擦除空间。

A std::list会更好;你可以并行地维护一个指向这些项的指针向量,这将允许你通过索引访问它们,而不用在内存中移动。

+0

好吧,我想我会使用一个列表,然后缓存不应该是我的需要的负担 – jmasterx 2010-10-05 22:45:38

+0

或者,如果你想要一个'vector',你可以做'int myObject = 4',然后总是引用它作为'objects [myObject]'。 – 2010-10-05 22:48:00

+0

没有办法,因为4可能会改变,如果我删除3 – jmasterx 2010-10-05 22:53:46

1

如果您保持向量的大小相同,您可以通过在声明它之后调用reserve()来保证这个最大数量的元素,或者(如您所做的那样)声明它具有初始数量的元素,每个元素被构造为具有缺省值元素值。

如果您删除或添加元素,则可以随时重新分配底层存储。

既然您在这里使用原始指针,您可以使用NULL作为“空元素”标志来保持存储不变。由于您最初设置为99,所以它们都将为NULL(任何指针的默认值为矢量元素),除非您计划扩展列表,否则reserve是多余的。

一个选项,可以让你不用担心矢量存储将存储元素为boost::shared_ptr<Object>。然后,如果没有其他人使用它,则任何删除vector元素实际上只会实际为delete引用的Object实例。

boost::shared_ptr<Object> myObject; 
std::vector<boost::shared_ptr<Object> > objects(99); 

myObject = &objects[4]; 

objects.clear(); 
// myObject still valid since Object instance referenced thru shared_ptr 
0

奇怪,但没有人提到boost::stable_vector件事:

...引用和迭代器的stable_vector的元素仍然有效,只要该元素不会被删除,并已指定一个迭代器end()的返回值始终保持有效,直到销毁关联的stable_vector。

相关问题