[英]Is a std::vector pointer reliable?
說我有這個:
Object *myObject;
std::vector<Object> objects(99);
....
myObject = &objects[4];
可以安全地假設myObject的指針將始終有效,無論有多少大的object [],如果我刪除了一些對象,只要我從不擦除myObject指向的實際對象,就可以了嗎? 還是不同地工作? 如果上述方法不起作用,我還能怎么實現呢? 這是因為在我的設計中,我希望孩子有一個指向其父對象的指針,該指針是在添加孩子時由父對象分配的,但是父對象位於std :: vector中,我需要隨機訪問。 在我看來,std :: list會更好嗎?
謝謝
不,假設絕對不安全。
該標准說明了將/不會使標准容器上的迭代器無效的內容; 每當向量迭代器失效時,指向它的指針也將變為無效。 實際上,這意味着當向量調整大小時(包括在調用push_back()
時隱式包含),指向該向量的任何迭代器都會失效,指針也將無效。 同樣,在調用被擦除的項之后,調用erase()
將使指針無效,因為它們都必須向上移動以填充被擦除的空間。
一個std::list
會更好; 您可以並行維護指向項目的指針向量,這將使您可以通過索引訪問它們,而無需在內存中移動它們。
如果向量填滿了分配的空間,而您嘗試插入更多空間,則需要重新分配其存儲,這將涉及復制對象並破壞舊的存儲,這將使您保留的指針無效-因此不,這還不夠好。
std :: list可以正常工作,因為它不依賴於連續存儲,但是您失去了進行快速隨機訪問的能力。 另外,您可以在集合中存儲指向對象的指針,在這種情況下,您可以刪除該元素,並且指針將一直有效,直到您在代碼中釋放該內存為止-但您需要在某個時候自行處理。
另一個選擇可能是雙端隊列 ; 盡管雙端隊列迭代器被push_back
無效,但對元素的直接引用(例如您在此處使用的指針)仍然有效。
如果向量保持相同大小,則可以通過在聲明它之后或通過(如您所進行的)聲明初始數量的元素(每個構造為具有默認元素值reserve()
的最大數量的元素來調用reserve()
來保證這一點。 。
如果刪除或添加元素,則可以隨時重新分配基礎存儲。
由於您在此處使用原始指針,因此可以將NULL用作“空元素”標志,以保持存儲不變。 由於您最初將其設置為99,因此之后它們都將為NULL(任何指針作為矢量元素的默認值),並且reserve
是多余的,除非您打算擴展列表。
一個讓您不必擔心向量存儲的選項是將元素存儲為boost::shared_ptr<Object>
。 然后,如果沒有其他人使用vector
元素,則僅delete
其delete
實際上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
奇怪,但是沒有人提到boost :: stable_vector事情:
...只要未擦除穩定元素的元素的引用和迭代器就一直有效,並且分配了end()返回值的迭代器始終保持有效,直到關聯的穩定向量被破壞為止。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.