【问题标题】:Destructor is called on unwanted object during assignment在分配期间对不需要的对象调用析构函数
【发布时间】:2011-10-28 06:51:12
【问题描述】:
myClassVar = MyClass(3);  

我希望在左侧之前创建的 myClassVar 上调用析构函数。
但它实际上是在 MyClass(3) 创建的新对象上调用的。

我的完整测试代码和输出如下..

编辑

我该如何解决这个问题?
实现赋值运算符?
MyClass其实有指针,还有MYSQL_STMT*,不知该如何处理MYSQL_STMT*变量。

我只需要 MyClassVar(3) 对象,而不是在创建 ClientClass 对象时首先创建的 MyClassVar()。

我经常遇到这种情况,想知道是否有好的方法。

#include <stdio.h>

class MyClass
{
public:
    MyClass() { printf("MyClass %p\n", this); }
    MyClass(int a) { printf("Myclass(int) %p\n", this); }
    ~MyClass() { printf("~MyClass %p\n", this); }

private:
    int mA;
};


class ClientClass
{
public:
    void Foo()
    {
        printf("before &myClassVar : %p\n", &myClassVar);
        myClassVar = MyClass(3); // this is the important line
        printf("after &myClassVar : %p\n", &myClassVar);
    }

private:
    MyClass myClassVar;
};

int main()
{   
    ClientClass c;
    c.Foo();
    return 0;
}

MyClass 0x7fff5fbfeba0
before &myClassVar : 0x7fff5fbfeba0
Myclass(int) 0x7fff5fbfeb70
~MyClass 0x7fff5fbfeb70 // <--- here destructor is called on the newly created object
after &myClassVar : 0x7fff5fbfeba0
~MyClass 0x7fff5fbfeba0

【问题讨论】:

  • 我已经编辑了我的答案以解决您的编辑问题。

标签: c++ variable-assignment destructor


【解决方案1】:

以下是关键线的分解方式:

myClassVar = MyClass(3);

首先,MyClass(3) 调用构造函数并返回对象。

其次,myClassVar = 将对象复制到myClassVar

然后语句结束。对象(立即数)已死,因此调用了析构函数。

编辑:

至于如何解决这个问题。我能想到的唯一方法是使用placement new。除了制作“set”方法之外,我不确定是否有更好的解决方案。

【讨论】:

  • “set”方法是指拷贝构造函数和赋值运算符?
  • 更像是一种单独的方法,以有效的方式将两者结合起来。基本上,它会破坏现有对象并在其位置创建一个新对象。 (这必须在类中定义)
【解决方案2】:
myClassVar = MyClass(3);

myClassVar 在此行之后继续存在。 MyClass(3) 的生命周期以分号结束。

【讨论】:

    【解决方案3】:

    正如其他帖子提到的那样,具有自定义构造函数MyClass(3) 的对象在赋值操作myClassVar = MyClass(3) 后被销毁。在这种情况下,您不需要自定义赋值运算符,因为编译器生成一个将成员 mA 复制到已经存在的对象 myClassVar。

    但是,由于 MyClass 定义了自己的析构函数,您应该遵守 rule of three,它要求在这种情况下您也应该实现自定义赋值运算符。

    【讨论】:

      【解决方案4】:

      回应您的编辑:您如何解决什么问题?不清楚 问题是什么。如果您的班级需要析构函数(并且没有 多态性),它可能需要赋值运算符和 复制构造函数。同样,当“跟踪”建筑和 破坏,你可能也应该提供两者,因为它们会 被调用。

      否则:如果问题在于您正在构建,然后 分配,而不是立即用正确的值构造, 简单的答案是“不要这样做”。编译器按你说的做 到。如果你写:

      MyClass var;
      var = MyClass(3);
      

      你有默认构造,后面跟着一个构造 临时的、分配的和临时的销毁。如果你 写:

      MyClass var(3);
      

      MyClass var = 3;
      

      你只有一个结构。 (请注意,尽管出现,有 在最后一个 sn-p 中是 no 分配。只有建筑。)

      对于班级成员,这种差异体现在您编写 构造函数:

      ClientClass::ClientClass() { var = MyClass(3); }
      

      是默认构造,后面是创建、赋值和 临时销毁;

      ClientClass::ClientClass() : var( 3 ) {}
      

      只是具有正确值的构造。 (很明显,这 第二种形式是首选。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-29
        • 2020-03-28
        • 2016-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多