#include <iostream>
using namespace std;
class A
{
public:
A() { cout << "A's constructor" << endl; }
~A() { cout << "A's destructor" << endl; }
};
class B
{
public:
operator A() const { return A(); }
};
void f(A q) {}
int main()
{
B d1;
f(d1);
return 0;
}
这是我在运行代码之前要做的事情: 对f的调用导致调用B类中的转换器函数,该函数返回一个临时对象。 q的构造函数被调用,当f退出时,q的析构函数被调用。我期待以下输出:
A的构造函数
A的析构函数
但我得到的输出是:
A的构造函数
A的析构函数
A的析构函数
由于还有另一个析构函数,因此必须在某处创建一个额外的对象。有人能解释一下这里发生了什么吗?
答案 0 :(得分:1)
将此作为您的班级A:
class A
{
public:
A() { cout << "A's constructor: " << this << endl; }
A(const A& a) { cout << "A's copy constructor: " <<this << " form " << &a << endl; }
A(A&& a) { cout << "A's move constructor: " <<this << " form " << &a << endl; }
A& operator=(const A& a) { cout << "A's assignment" <<this << " form " << &a << endl; }
~A() { cout << "A's destructor: "<< this << endl; }
};
你会明白为什么。
答案 1 :(得分:0)
这里有3个A
个对象的可能性。首先是转换运算符中A()
创建的临时对象。然后,由于转换运算符的返回类型为A
,因此将临时值复制到返回值中。然后,转化的返回值将复制到q
的参数f
。
要复制对象,将调用复制构造函数。不会调用默认构造函数,因此您不会看到正在打印的“A的构造函数”消息。
恰好,编译器忽略了这些副本中的一个,因此实际上只有一个副本出现。哪一个被省略,我不能告诉你(但它可能是复制到返回值)。
答案 2 :(得分:0)
我认为第一个析构函数调用临时对象,而第二个析构函数是由移动语义构造的对象。
答案 3 :(得分:0)
之前已经多次询问过这个问题,但由于它如此通用,很难找到较旧的帖子。
您正在通过值传递周围的对象,这意味着副本由复制构造函数创建。复制构造函数是在您的情况下创建“额外对象”的原因。同时,您不会从复制构造函数中输出任何内容,因此看不到调用。
您还必须向复制构造函数添加调试输出。这样你就会看到实际构造的内容和时间。