2016-12-25 57 views
0
#include <iostream> 
#include <cstring> 
#include <vector> 

using namespace std; 

class items{ 
    char * name; 
public: 
    items(const char * str){ 
     int len = strlen(str); 
     this->name = new char [len]; 
     strcpy(this->name,str); 
     cout << "Default ctor " << this->name << " \[email protected]" << (this) << endl; 
    } 

    items(const items& obj){ 
     int len = strlen(obj.name); 
     this->name = new char [len]; 
     strcpy(name,obj.name); 
     cout << "Copy ctor " << this->name << " \[email protected]" << this << endl; 
    } 

    ~items(){ 
     cout << "dtor \t" << this->name << "\[email protected]" << this << endl; 
     delete [] name; 
    } 

    const char * getName() const{ 
     return this->name; 
    } 
}; 

ostream& operator<<(ostream& stream, const items& obj){ 
    stream << obj.getName(); 
    return stream; 
} 

int main(int argc, char ** argv){ 
    items Ruler("Ruler"), Pencil("Pencil"), Book("Book"), Notebook("Notebook"), Sharpener("Sharpener"); 


    vector<items> school; 
    school.push_back(Ruler); 
    school.push_back(Pencil); 
    school.push_back(Book); 

    return 0; 
} 

我有奇怪的結果。你能解釋一下現場發生的事情嗎? 結果:太多複製ctors我無法弄清楚

Default ctor Ruler @0x62ff1c 
Default ctor Pencil  @0x62ff18 
Default ctor Book @0x62ff14 
Default ctor Notebook @0x62ff10 
Default ctor Sharpener @0x62ff0c 
Copy ctor Ruler  @0x9cd1d0 
Copy ctor Pencil @0x9cd504 
Copy ctor Ruler  @0x9cd500 
dtor Ruler @0x9cd1d0 
Copy ctor Book @0x9c0510 
Copy ctor Ruler  @0x9c0508 
Copy ctor Pencil @0x9c050c 
dtor Ruler @0x9cd500 
dtor Pencil @0x9cd504 
dtor Ruler @0x9c0508 
dtor Pencil @0x9c050c 
dtor Book @0x9c0510 
dtor Sharpener @0x62ff0c 
dtor Notebook @0x62ff10 
dtor Book @0x62ff14 
dtor Pencil @0x62ff18 
dtor Ruler @0x62ff1c 

默認構造後發生了什麼?爲什麼這個統治者創造太多副本並摧毀他們?這裏有什麼問題?

+2

你的「默認構造函數」根本不是默認的構造函數,這很容易讓人誤解。 – Quentin

+0

如果你解釋一下你期望的副本,我們會更好地解釋你的誤解。 – user2357112

+0

當你推動你的項目上的矢量臨時副本製作 – FamZ

回答

1

基本上發生的事情是,如果一個向量已滿並且您正在推送一個元素,則該向量需要調整大小。所以當你在矢量上推Ruler時,會創建一個大小爲sizeof(items)的數組,並將數據複製到(第一個拷貝的構造函數調用Ruler)。然後你在向量上推Pencil(第一個拷貝構造函數調用Pencil),但是向量內存不足,所以新的數組被分配了前一個大小的兩倍2 * sizeof(items),舊數組被複制到新數組(第二個拷貝構造函數調用了Ruler)和舊陣列被破壞(在舊陣呼籲Ruler第一析構函數)等等...

1

std :: vector管理自己的內存。這意味着std :: vector只存儲對象的拷貝,這意味着對象必須有一個有意義的拷貝構造函數(和一個賦值操作符,但這是另一個問題)。

當矢量的析構函數被調用時,矢量所持有的內存被釋放。當std :: vector被移除時(通過擦除,pop_back,清除或向量的析構函數),std :: vector也會調用對象的析構函數。

2

你的「默認構造函數」需要一個參數,並且,因此,沒有一個默認的構造函數中C++的意義:默認的構造函數可以在沒有任何參數的情況下調用。

關於你的問題似乎順序是這樣的:

  1. 最初都得到構造的對象。
  2. 有一個Ruler對象的副本將其插入到school向量中。
  3. 當插入Pencil時,首先複製此對象,但顯然school向量中沒有足夠的空間:將Pencil對象複製到新分配的位置,然後複製Ruler並將原始空間銷燬。
  4. 當插入Book時,會發生相同的順序:將Book複製到新位置,然後在那裏複製RulerPencil
  5. 最後,所有的對象被破壞。

序列是在這個意義上有些混亂的是std::vector通常不表現得像是:它通常就在其中可容納一個以上的元素的開始創建一個小的陣列。看起來,所使用的實現從一個capacity()開始,然後從那裏增加一倍。您可以通過調用school.push_back()之間的school.capacity()來驗證此行爲:無論何時capacity()增加,底層數組都會增加。

考慮到你正在分配內存,你可能需要考慮一個移動構造函數來傳遞存儲的內存,而不是分配一個新的數組來容納一個副本,然後只是原始的delete。移動的構造函數看起來像這樣:

items::items(items&& other) 
    : name(other.name) { 
    this->name = nullptr; 
}