这是我的前任:
N
所以,我得到了这个输出:
#include <iostream>
#include <vector>
class A {
public:
A() { std::cout << "Constructor\n"; }
~A() { std::cout << "Destructor\n"; }
};
class B {
public:
B() { v.push_back(A()); v.push_back(A()); }
private:
std::vector<A> v;
};
int main() {
B b;
return 0;
}
有人可以解决一些问题吗?
跟随Dave的评论后:
Constructor // first push back
Destructor // copy destroyed
Constructor // second push back
Destructor // copy destroyed
Destructor // ???????????????
// B object goes out of scope and its vector too...
Destructor // v[0] destructor called
Destructor // v[1] destructor called
答案 0 :(得分:3)
添加一个重载的复制构造函数以及正在对哪个对象采取行动的一些指示器可以解释这种情况:
#include <iostream>
#include <vector>
class A {
public:
A(unsigned i): i(i) { std::cout << "Constructor " << i << std::endl; }
A(const A& a) : i(a.i) { std::cout << "Copy constructor " << i << std::endl; }
~A() { std::cout << "Destructor " << i << std::endl; }
unsigned i;
};
class B {
public:
B() { v.push_back(A(0)); v.push_back(A(1)); }
private:
std::vector<A> v;
};
int main() {
B b;
return 0;
}
在第一次推送时,我们制作副本并销毁临时版。在第二次推送时,我们制作一个副本,然后复制第一个对象,然后销毁第一个对象和临时对象。最后,我们销毁这两个对象。
我猜测std :: vector首先被分配了1的容量,所以第二次推送强制重新分配?如果我强制更大的初始容量(通过在第一次推送之前调用v.reserve(5)
),那么额外的副本就会消失。
答案 1 :(得分:2)
您没有使用默认的复制构造函数跟踪A
的构造。如果在其中添加了复制构造函数和消息,那么对构造函数的调用次数应该与析构函数的调用次数相匹配。
答案 2 :(得分:2)
按如下方式修改A类声明,
class A
{
public:
A() { std::cout << "Constructor " << this << std::endl; }
A(const A&) { std::cout << "Copy Constructor " << this << std::endl; }
~A() { std::cout << "Destructor " << this << std::endl; }
};
在http://coliru.stacked-crooked.com/运行该程序 给出输出:
构造函数0x7fffecb8dc0f
复制构造函数0x1efdc20
析构函数0x7fffecb8dc0f
构造函数0x7fffecb8dc0e
复制构造函数0x1efdc41
复制构造函数0x1efdc40
析构函数0x1efdc20
析构函数0x7fffecb8dc0e
析构函数0x1efdc40
析构函数0x1efdc41
清楚地显示堆栈和堆上对象的构造和破坏(0x1efdc20,0x1efdc40和0x1efdc41是向量分配的对象的位置)。