在分配期间,在不需要的对象上调用析构函数

时间:2011-10-28 06:51:13

标签: c++ variable-assignment destructor

myClassVar = MyClass(3);  

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

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

修改

如何解决问题?
实现赋值运算符?
MyClass实际上有指针和MYSQL_STMT *,我想知道我应该如何处理MYSQL_STMT *变量。

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

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

#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

4 个答案:

答案 0 :(得分:6)

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

myClassVar = MyClass(3);

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

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

然后声明结束。 <(立即)对象已死,因此调用析构函数。

编辑:

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

答案 1 :(得分:2)

myClassVar = MyClass(3);
此行之后

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

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

否则:如果问题是你正在构建,那么 分配,而不是立即构造正确的值, 简单的答案是“不要这样做”。编译器会按照您的说法执行操作 至。如果你写:

MyClass var;
var = MyClass(3);

你有默认构造,然后构建一个 暂时的,分配和临时的破坏。如果你 写:

MyClass var(3);

MyClass var = 3;

你只有一个建筑。 (注意,尽管有外表,但有 最后一个片段中的分配。只有建筑。)

对于班级成员,这种差异出现在你写作的方式中 构造:

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

是默认构造,后跟创建,赋值和 破坏一个临时的;

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

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