2010-07-24 47 views
3

說我有兩個容器存儲指向相同的對象:從STL容器中移除元素時調用析構函數嗎?

std::list<Foo*> fooList; 
std::vector<Foo*> fooVec; 

比方說,我通過一個,如果它的方法去除從這些容器中的一個對象:

std::vector<Foo*>::iterator itr = 
    std::find(fooVec.begin(), fooVec.end(), pToObj); 
fooVec.erase(itr); 

CppReference說,這個電話對象的析構函數。這是否意味着指向fooList中的對象的指針是一個懸掛指針?

我不想使用引用計數的指針。這個問題怎麼處理?

+1

使用引用計數的指針。這就是他們的目的。 – Puppy 2010-07-24 18:31:54

回答

6

當您從容器中取出一個指針,你所做的一切是採取從容器中的指針值,沒有被刪除。 (即:指針沒有析構函數)。

但是,容器中的指針是很危險的。考慮:

std::vector<int*> v; 
v.push_back(new int()); 
v.push_back(new int()); 
v.push_back(new int()); 

如果您從未通過容器並刪除每個容器,則已泄漏。更糟的是它不是特例安全。您應該使用pointer container,這將刪除它們在被擦除時指向的內容。 (當容器破壞時,所有東西都會被擦除。)

但是,就你而言,由於你在不同的地方共享一個指針,所以我看不到針對shared_ptr的參數;這正是它所做的。

+0

請爲我解決這個問題。爲什麼list :: erase的文檔會說''這會通過刪除的元素數量有效地減少容器的大小,這些元素被銷燬。「#http://www.cplusplus.com/reference/list/list/erase/ – matrixugly 2016-09-02 18:15:24

+0

@matrixugly :你應該使用cppreference,它更好:http://en.cppreference.com/w/cpp/container/list/erase。正如它在那裏澄清的那樣,有兩種「擦除」重載。我們需要一系列迭代器,並且每個元素都會被擦除。 – GManNickG 2016-09-03 04:07:28

1

我不認爲該對象的析構函數會被調用。 fooList中的指針仍應指向有效數據。

如果您指的是this link,它是在討論如何調用erase會使您指向向量中後續位置的任何迭代器失效。但是使迭代器無效與在向量中的一個事物上調用delete不同。

0

當您有一個指向對象的原始指針時,除非刪除它,否則不會調用析構函數。

您可以用來確保您的對象在正確的時間被刪除並使用指針容器(如許多算法所需)的模式(或者它是一個成語?)是使用單獨的雙端存儲器來存儲實際的物體。您必須確保在任何指針容器後deque都被銷燬。你應該使用deque而不是vector的原因是你可以添加對象到deque而不會使指向先前存儲對象的指針失效。

0

兩個容器都持有對(Foo *)對象的引用 - 所以如果析構函數被調用,它就是指針對象的析構函數(可能什麼也不做),而不是Foo對象本身。原始對象(類Foo)不被破壞,因此沒有懸掛引用。

0

在您的情況下,存儲在容器中的對象是原始指針的副本,而不是原始指針。因此,對於您決定存儲的每個Foo*,您都將有3個指針(原始文件,fooList中的一個和fooVec中的一個),全部指向內存中的相同位置。 所以當你調用erase時,刪除將在指針本身而不是它指向的內容上被調用,並且指針上的刪除是沒有操作的(它們沒有像GMan說的那樣的析構函數)。

相關問題