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
答案 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 ) {}
只是具有正确值的构造。 (显然,这个 第二种形式是首选。)