2016-12-25 47 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; 
}