下面是 C++ 中 vector 推回方法的签名。
void push_back (const value_type& val);
下面是代码
class MyInt
{
int *a;
public:
MyInt(int n):a(new int(n)){cout<<"constructor called"<<endl;}
~MyInt(){cout<<"destructor called"<<endl;}
void show(){
cout<<*a<<endl;
}
};
void vector_test(vector<MyInt> &v)
{
MyInt m1(1);
MyInt m2(2);
v.push_back(m1);
v.push_back(m2);
}
Output
-------------
constructor called
constructor called
destructor called
destructor called
destructor called
1
2
destructor called
destructor called
这里我们看到在 vector_test 函数中创建的 2 个对象导致 2 次 构造函数调用。 但对于析构函数,它被调用了 5 次。
现在我的疑惑和问题是
- 为什么构造函数和析构函数的调用次数不匹配?
- 我了解到正在创建一些临时对象。但这种机制是如何运作的?
- 只是为了测试,我尝试提供一个复制构造函数,但它会导致编译失败。可能是什么原因?
- 是否有一些逻辑将 m1 和 m2 的内容复制到新对象中并放入容器中?
如果有人能详细解释一下,我将不胜感激。谢谢..
最佳答案
您还需要为复制构造函数添加日志记录:
MyInt(const MyInt& rhs):a(new int(*rhs.a)){cout<<"copy constructor called"<<endl;}
编译器允许省略某些构造函数调用,即。在以下行中:
MyInt m1 = 1;
您可能希望首先调用复制构造函数来实例化临时 MyInt(1)
然后用这个临时调用一个复制构造函数。所以你会看到:
constructor called // for temporary
copy constructor called // for m1
destructor called // for m1
destructor called // for temporary
但由于复制省略编译器将直接实例化您的 m1
使用 MyInt(int n)
的实例构造函数,即使您的复制构造函数有副作用(使用 std::cout)。所以没有以上 // for temporary
日志将存在。
要使用 gcc 查看此信息,请使用:-fno-elide-constructors
禁用复制构造函数省略的选项。
此外,构造函数也是一个好习惯,例如 MyInt(int n)
明确的,这是不允许制作MyInt
错误的对象实例 - 你必须将其明确化,即 MyInt var; var = static_cast<MyInt>(1);
.
关于C++ vector push_back 方法和临时对象创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37078038/