问题描述
这里,当我入栈时,为什么对象被销毁了?
#include <iostream>
#include <stack>
class One
{
private:
int i;
public:
One(int i) {this->i = i;}
~One() {std::cout << "value " << this->i << " is destroyed\n";}
};
int main()
{
std::stack<One> stack;
stack.push(One(1));
stack.push(One(2));
std::cout << "Now I'll stop\n";
}
我希望在 Now I'll stop
之前看不到任何输出。但我明白了
value 1 is destroyed
value 2 is destroyed
Now I'll stop
value 1 is destroyed
value 2 is destroyed
如果我想防止它们被破坏,我该怎么做?
解决方法
One(1)
和 One(2)
构造两个临时对象,将它们传递给 push
,然后复制(移动)到 stack
中。临时表在完整表达式后立即销毁。
如果您想避免构建临时文件,您可以改用 emplace
。
将一个新元素压入栈顶。元素是就地构造的,即不执行复制或移动操作。
例如
stack.emplace(1);
stack.emplace(2);
,
让我在解决实际问题的 songyuanyao's answer 中添加一个说明性细节。
如果您将 copy constructor 添加到类 One
,您将更容易理解发生了什么以及如何保持创建和销毁之间的平衡。 (对你来说,两个创造物获得 4 次破坏是不是很神奇?)
只要您没有定义(或提及)copy constructor,编译器就会为您创建一个具有简单实现的实现,该实现对所有成员进行按位复制。因此,在您的情况下,您观察到的行为可能令人困惑,但并没有做任何特别糟糕的事情。这当然会在您添加涉及不仅仅是复制的成员时立即改变,例如指向必须在某处销毁的成员的指针......
在以下示例中,我向两个构造函数都添加了输出,并且还从在构造函数主体中分配成员切换为 initialiser list:
class One
{
public:
One(int rhs): i(rhs) {
std::cout<< "value " << i << " was created from int\n";
}
One(const One& rhs): i(rhs.i) {
std::cout<< "value " << i << " was created by copy\n";
}
~One() {
std::cout << "value " << i << " is destroyed\n";
}
private:
int i;
};
,
执行此操作时 stack.push(One(1));
会创建一个名为 One(1)
的 rvalue 的临时对象,然后将其复制到 Stack。所以在 Copy 之后,临时对象会被销毁。