#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
默认构造后发生了什么?为什么这个统治者创造了太多副本并摧毁它们?这有什么问题?
答案 0 :(得分:2)
你的“默认构造函数”接受一个参数,因此,它不是C ++意义上的默认构造函数:可以不带任何参数调用默认构造函数。
关于你的问题,似乎序列是这样的:
Ruler
对象的副本将其插入school
向量。Pencil
时,首先复制此对象,但显然school
向量中没有足够的空间:Pencil
对象被复制到新分配的位置,然后{复制{1}}并销毁原始空间。Ruler
时会发生相同的序列:Book
被复制到新位置,然后Book
和Ruler
也会被复制到那里。序列有点令人困惑,因为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
)依此类推......