为什么在函数内部初始化时 C++ 对象会被销毁?我能做些什么来防止它?

Why are C++ objects destroyed when initialized inside function? What can I do to prevent it?

这里,我压栈的时候,为什么对象被销毁了?

#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

Pushes a new element on top of the stack. The element is constructed in-place, i.e. no copy or move operations are performed.

例如

stack.emplace(1);
stack.emplace(2);

执行此操作时 stack.push(One(1)); 它会创建一个临时对象,称为 One(1) 的右值,然后将其复制到 Stack。所以复制后,临时对象被销毁。

让我在 中添加一个说明细节,它解决了实际问题。

如果你在 class One 中添加一个 copy constructor,你会更容易理解发生了什么,以及 如何 之间的平衡创造和破坏得以维持。 (对你来说,两次造物获得 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;
};