我正在玩destructor
和operetor=
,输出对我来说很奇怪。
两个版本的主要功能:
int main()
{
B b1;
B b2;
b2=b1;
cout<<"---"<<endl;
return 0;
}
class B
{
public:
B operator=(B& b1)
{
cout<<"operator="<<endl;
return b1;
}
~B()
{
cout<<"destructor"<<endl;
}
};
输出:
operator=
destructor // Did it print because `b2` got new value so the old value is going to trash?
--
destructor
destructor
B&
而不是B
,输出不一样;析构函数被调用两次而不是之前的三次。为什么?
class B
{
public:
B& operator=(B& b1)
{
cout<<"operator="<<endl;
return b1;
}
~B()
{
cout<<"destructor"<<endl;
}
};
输出:
operator=
--
destructor
destructor
答案 0 :(得分:2)
在第一种情况下,您还有一个额外的实例:
int main()
{
B b1;
B b2;
b2=b1; <---- here b2.operator=(b1) returns another B instance
(its a copy of b1)
cout<<"---"<<endl;
return 0;
}
在行尾已被破坏,因为你没有保留对它的引用。你可以写:
B b3 = (b2=b1);
使实例保持活动状态直到范围结束。在这种情况下,您会看到在打印---
后调用析构函数。
另请注意,在操作符应将*this
的引用返回给其他实例的情况下,两个运算符都不正确。 (在PaulMcKenzie的评论中已经提到过,只需在此重复一遍以确保它不会丢失)
答案 1 :(得分:0)
代码工作正常并且符合预期。在第一种情况下,析构函数在&#34; operator =&#34;之后被调用。因为您要返回B对象的本地副本:
B operator=(B& b1)
{
cout<<"operator="<<endl;
return b1;
}
请注意声明&#34;返回b1&#34;将返回本地副本(而不是引用),并且一旦作用域结束它将被破坏。您可以通过编写自己的复制构造函数来测试验证这一点,并在其中添加一条跟踪。我做了以下事情:
class B
{
public:
B operator=(B& b1)
{
cout<<"operator="<<endl;
return b1;
}
~B()
{
cout<<"destructor"<<endl;
}
B(const B& b1){
cout << "Copy constructor called" << endl;
}
B(){}
};
我得到了以下输出:
operator=
Copy constructor called
destructor
---
destructor
destructor
然而,在赋值运算符重载的返回类型为B&amp;的第二种情况下,永远不会调用复制构造函数,因为它将返回对它接收的对象的引用,而不是副本。因此,对于在main()方法中创建的对象b1和b2,析构函数只会被调用两次。 希望这能解答您的疑问。