4 回答
默认构造函数只构造一个对象,然后将其复制 5 次。添加:
A(const A&) { cout << "copy-constructor is called" << endl; }
通过复制初始对象来查看其他对象的创建时间/位置。
将您的代码更改为:
class A {
public :
string name;
int age;
A(){ cout << "constructor is called" << endl; }
~A() { cout << "destructor is called"<< endl; }
A(const A&) { cout << "copy c'tor is called"<<endl;}
};
那么你会得到
constructor is called
copy c'tor is called
copy c'tor is called
copy c'tor is called
copy c'tor is called
copy c'tor is called
destructor is called
5
destructor is called
destructor is called
destructor is called
destructor is called
destructor is called
如您所见,您的对象创建了一次,但复制了 5 次。
首先,该代码的行为取决于您的编译器和库正在实施的标准版本。您描述的行为是 C++03 实现的行为,您使用的向量构造函数是:
explicit vector(size_type n, const T& value = T(),
const Allocator& = Allocator());
您没有提供值或分配器,因此它们是默认的。相反,如果您明确创建对象,您将了解发生了什么:
vector<A> vec(5,A()); // A() is a temporary, destroyed at the end of the
// whole expression.
也就是说,使用默认构造函数创建一个临时对象,生成构造函数调用的跟踪,并用于复制到 5 个位置。然后它在表达式的末尾被销毁。当向量超出范围时,存储在其中的 5 个元素会自行销毁。
在 C++11 中,库发生了变化,现在上面的签名分为这两个签名:
explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());
使用 C++11 实现,您将调用两者的第一个版本。在这种情况下,构造函数没有参数,因此不会创建临时的。相反,新标准要求实现默认在适当位置构造元素。因此,程序的输出将是 5 行表示创建向量时的默认构造函数,而 5 行表示向量超出范围时析构函数的输出。
向量的工作方式如下:
您放入向量中的东西是该东西的副本。你从向量中得到的东西是向量中的东西的副本。
构造函数的工作方式为(假设您的类是 A):
A array[n]; // This one will call default constructor n times
vector<A> vec(n); // This one will call default constructor once and copy constructor n times.
具有默认构造函数的必不可少的一个对象创建一个对象,这个对象没有放入向量中
你得到一个原始的和 5 个副本,这就是为什么有 6 次析构函数被调用