为了账号安全,请及时绑定邮箱和手机立即绑定

在C ++中复制构造函数和=运算符重载:是否可能使用通用函数?

在C ++中复制构造函数和=运算符重载:是否可能使用通用函数?

C++
慕无忌1623718 2019-10-15 10:07:23
由于复制构造函数MyClass(const MyClass&);和=运算符重载MyClass& operator = (const MyClass&);具有几乎相同的代码,相同的参数,并且仅在返回值上有所不同,是否可以为它们两者使用共同的功能?
查看完整描述

3 回答

?
紫衣仙女

TA贡献1839条经验 获得超15个赞

复制构造函数对曾经是原始内存的对象执行首次初始化。赋值运算符OTOH用新值覆盖现有值。通常涉及解散旧资源(例如,内存)并分配新资源。


如果两者之间有相似之处,那就是赋值运算符执行销毁和复制构造。一些开发人员过去实际上是通过就地销毁,然后是布局复制构造来实现分配的。但是,这是一个非常糟糕的主意。(如果这是派生类分配期间调用的基类的赋值运算符,该怎么办?)


swap正如Charles所建议的,如今通常被认为是规范用语的是:


MyClass& operator=(MyClass other)

{

    swap(other);

    return *this;

}

这使用了复制构造(注意other已复制)和销毁(它在函数末尾被销毁)-并且它也以正确的顺序使用它们:销毁(必须失败)之前的构造(可能失败)。


查看完整回答
反对 回复 2019-10-15
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

有些事情困扰着我:


MyClass& operator=(const MyClass& other)

{

    MyClass tmp(other);

    swap(tmp);

    return *this;

}

首先,当我的思想是“复制”时,读“交换”一词会激怒我的常识。另外,我对这个幻想的目的提出了质疑。是的,在构造新的(复制的)资源时,任何异常都应该发生在交换之前,这似乎是一种确保所有新数据都被填充后才能上线的安全方法。


没关系。那么,交换之后发生的异常又如何呢?(当临时对象超出范围时,旧资源被破坏时)从分配用户的角度来看,该操作失败了,但没有失败。它具有巨大的副作用:复制确实发生了。只是某些资源清除失败。即使从外部看来操作失败,目标对象的状态也已更改。


因此,我建议不要“交换”来进行更自然的“转移”:


MyClass& operator=(const MyClass& other)

{

    MyClass tmp(other);

    transfer(tmp);

    return *this;

}

仍然存在临时对象的构造,但是下一个直接的操作是在将源的资源移动到目的地之前,释放目标的所有当前资源(并且为NULL,这样它们就不会被双重释放)。


我提出了{构造,破坏,移动}而不是{构造,移动,破坏}。此举是最危险的举动,是在解决所有其他问题后采取的最后一步。


是的,无论哪种方案,销毁失败都是一个问题。数据已损坏(在您不认为是复制时复制)或丢失(在您不认为是被释放时释放)。丢失总比损坏好。没有数据比坏数据更好。


转移而不是交换。无论如何,这是我的建议。


查看完整回答
反对 回复 2019-10-15
  • 3 回答
  • 0 关注
  • 428 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信