2015-11-04 65 views
1
#include <iostream> 
#include <vector> 
using namespace std; 

class cMember 
{ 
    public: 
    int id; 

    cMember(); 
    ~cMember(); 
}; 

cMember::cMember() 
{ 
    cout<<"member constructor\n"; 
} 

cMember::~cMember() 
{ 
    cout<<"member destructor\n"; 
}; 

class cDirectory 
{ 
    std::vector<cMember> memberList; 

public: 
    cDirectory(); 
    ~cDirectory(); 

    void Populate(); 
}; 


cDirectory::cDirectory() 
{ 
    cout<<"directory constructor\n"; 
} 

cDirectory::~cDirectory() 
{ 
    cout<<"directory desctructor\n"; 
} 

void cDirectory::Populate() 
{ 
    for(int i = 0; i < 2; i++) 
    { 
     cout<<"A\n"; 
     cMember t; 
     memberList.push_back(t); 
     cout<<"B\n"; 
    } 
    cout<<"C\n"; 
} 

int main(int argc, const char ** argv) 
{ 
    cDirectory dir; 
    dir.Populate(); 
    exit(0); 
} 

查看該程序的輸出,第二次迭代調用A和B之間的成員析構函數。我假設這個調用是重新分配和重新填充的矢量,並且在重新分配之前銷燬其中的成員。矢量破壞對象但不構建它們的替換物?

vector如何破壞對象,但不構造它們的替換物?

+1

閱讀「3規則」。你也應該在你的類中有一個拷貝構造函數和賦值操作符。 – Joe

+0

如你所知,vector通過調用拷貝構造函數來做深層拷貝 – blade

+0

如果你想調用默認的構造函數而不是拷貝構造函數,你可以'emplace()'新元素。 – Davislor

回答

0

因爲cMember是靜態分配的,當函數超出範圍內存將會丟失。如果它在內存中仍然有對該點的引用,那麼對於該向量來說這將是有問題的。相反,std::vector將複製構造該對象。這爲向量提供了自己的動態分配副本,即使在函數超出範圍之後,該副本也將存在於該向量中。

我修改代碼以打印this爲好,這是輸出:

directory constructor 
A 
member constructor 0x7fff572e86f8 
B 
member destructor 0x7fff572e86f8 
A 
member constructor 0x7fff572e86f8 
member destructor 0x7fc1dbc04c80 
B 
member destructor 0x7fff572e86f8 
C 

正如你所看到的,被A和B之間銷燬對象不是由您的功能構造的。相反,它是由std::vector使用的複製構造對象。

+0

這個答案很有意義,但是我的問題出現了,因爲實際情況比我發佈的代碼示例稍微複雜一些。添加一個指向cMember的指針並在析構函數中刪除它,這就成了一個問題。對不起原來的問題沒有說清楚。有沒有處理這個問題的典型方法? – BDO

+1

您需要編寫自定義副本構造函數,並在該副本構造函數中爲副本分配新內存(而不是僅分配指針)。或者,如果你不想每次分配更多的內存,並且兩個對象應該使用相同的指針(沒有解除分配問題),你可以考慮使用來自C++ 11的智能指針:http://en.cppreference。 com/w/cpp/memory/shared_ptr – personjerry

+0

我想我通過永遠不要推動靜態分配的對象來避免這個問題。當指向的對象不再需要時,我總是使用指針向量和清理例程。感謝您的解釋和解決方案! – BDO

5

向量如何銷燬對象,但不構建它們的 替換?

它通過調用拷貝構造函數對象的而不是用戶定義的默認構造一個他們。

也就是說,如果你沒有爲一個對象定義一個拷貝構造函數,編譯器會爲你隱式定義一個拷貝構造函數。這裏也是這種情況。當您的矢量緩衝區被重新分配時,每個對象的複製構造函數都會被調用,以便將對象複製到新位置。你可以看到這一點,如果你定義拷貝構造函數如下:

class cMember { 
public: 
    int id; 
    cMember(); 
    CMember(cMember const&); 
    ^^^^^^^^^^^^^^^^^^^^^^^^ 
    ~cMember(); 
}; 

cMember::cMember(cMember const &) { 
    cout<<"member copy constructor\n"; 
} 

LIVE DEMO