太多复制ctors我无法弄清楚

时间:2016-12-25 20:54:48

标签: c++ constructor destructor

#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 << " \t@" << (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 << " \t@" << this << endl;
    }

    ~items(){
        cout << "dtor \t" << this->name << "\t@" << 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;
}

我有奇怪的结果。你能解释一下幕后发生的事情吗? 结果:

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

默认构造后发生了什么?为什么这个统治者创造了太多副本并摧毁它们?这有什么问题?

3 个答案:

答案 0 :(得分:2)

你的“默认构造函数”接受一个参数,因此,它不是C ++意义上的默认构造函数:可以不带任何参数调用默认构造函数。

关于你的问题,似乎序列是这样的:

  1. 最初对象都构建完毕。
  2. Ruler对象的副本将其插入school向量。
  3. 插入Pencil时,首先复制此对象,但显然school向量中没有足够的空间:Pencil对象被复制到新分配的位置,然后{复制{1}}并销毁原始空间。
  4. 插入Ruler时会发生相同的序列:Book被复制到新位置,然后BookRuler也会被复制到那里。
  5. 最后,所有对象都被破坏了。
  6. 序列有点令人困惑,因为Pencil通常不会表现得那样:它通常在开始时创建一个小数组,可以容纳多个元素。似乎,所使用的实现从一个std::vector开始,然后从那里加倍容量。您可以通过在capacity()调用之间查看school.capacity()来验证此行为:每当school.push_back()增加时,基础数组都会增加。

    考虑到你正在分配内存,你可能需要考虑一个移动构造函数来传输存储的内存,而不是分配一个新的数组来容纳一个副本,然后只需capacity()原始内存。移动构造函数看起来像这样:

    delete

答案 1 :(得分:1)

std :: vector管理自己的内存。这意味着std :: vector只存储一个对象的副本,这意味着该对象必须有一个有意义的复制构造函数(和赋值运算符,但这是另一个问题)。

当调用向量的析构函数时,向量所占用的内存被释放。 std :: vector在删除对象时也会调用对象的析构函数(通过erase,pop_back,clear或vector的析构函数)。

答案 2 :(得分:1)

基本上发生的事情是,如果向量已满并且您正在推送元素,则向量需要调整大小。因此,当您在向量上按Ruler时,会创建一个大小为sizeof(items)的数组,并将数据复制到(Ruler的第一个复制构造函数调用中)。然后你在向量上推Pencil(对Pencil的第一个复制构造函数调用),但是向量是内存不足的,所以一个新的数组被分配了前一个大小2 * sizeof(items)的两倍并将旧数组复制到新数组(第二个复制构造函数调用Ruler)并销毁旧数组(旧数组中第一个析构函数调用Ruler)依此类推......