繁体   English   中英

为什么在函数内部初始化时 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

将一个新元素压入堆栈顶部。 该元素是就地构造的,即不执行复制或移动操作。

例如

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

让我在宋元瑶的答案中添加一个说明细节来解决实际问题。

如果向One类添加复制构造函数,您将更容易理解发生了什么以及如何保持创建和销毁之间的平衡。 (对你来说,两个创造物获得 4 次破坏是不是很神奇?)

只要您不定义(或提及)复制构造函数,编译器就会为您创建一个具有简单实现复制构造函数,该实现对所有成员进行按位复制。 因此,在您的情况下,您观察到的行为可能令人困惑,但并没有做任何特别糟糕的事情。 这当然会在您添加涉及不仅仅是复制的成员时立即改变,例如指向必须在某处销毁的成员的指针......

在下面的示例中,我向两个构造函数都添加了输出,并且还从在构造函数体中分配成员切换到了初始化列表

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。 所以在复制之后,临时对象会被销毁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM