当你重载时operator=
,你可以写它来返回你想要的任何类型。如果你想要的不够严重,你可以重载X::operator=
以返回(例如)某个完全不同的类的实例Y
或Z
. 不过,这通常是非常不可取的。
特别是,您通常希望operator=
像 C 一样支持链接。例如:
int x, y, z;
x = y = z = 0;
在这种情况下,您通常希望返回被分配类型的左值或右值。这只留下了是否返回对 X 的引用、对 X 的 const 引用或 X(按值)的问题。
返回对 X 的 const 引用通常不是一个好主意。特别是,允许 const 引用绑定到临时对象。临时对象的生命周期延长到它所绑定的引用的生命周期——但不是递归地延长到可能分配给的任何引用的生命周期。这使得返回悬空引用变得容易——const 引用绑定到一个临时对象。该对象的生命周期延长到引用的生命周期(在函数末尾结束)。到函数返回时,引用和临时的生命周期已经结束,所以分配的是一个悬空引用。
当然,返回一个非常量引用并不能提供完全的保护,但至少会让你更加努力。您仍然可以(例如)定义一些本地,并返回对它的引用(但大多数编译器也可以并且也会对此发出警告)。
返回值而不是引用具有理论和实际问题。在理论上,您在=
通常的意思和在这种情况下的意思之间存在基本的脱节。特别是,赋值通常意味着“获取这个现有的源并将其值分配给这个现有的目标”,它开始意味着更像“获取这个现有的源,创建它的副本,并将该值分配给这个现有的目标。 "
从实际的角度来看,尤其是在右值引用被发明之前,这可能会对性能产生重大影响——在将 A 复制到 B 的过程中创建一个全新的对象是出乎意料的,而且通常很慢。例如,如果我有一个小向量,并将其分配给一个更大的向量,我希望最多花费时间来复制小向量的元素加上(小)固定开销来调整大小目标向量。如果这涉及到两个副本,一个从源到临时,另一个从临时到目标,以及(更糟)临时向量的动态分配,我对操作复杂性的期望将完全是被摧毁。对于一个小的向量,动态分配的时间很容易比复制元素的时间长很多倍。
唯一的其他选项(在 C++11 中添加)是返回一个右值引用。这很容易导致意想不到的结果——像这样的链式赋值a=b=c;
可能会破坏b
和/或的内容c
,这是非常出乎意料的。
这使得返回一个正常的引用(不是对 const 的引用,也不是一个右值引用)作为(合理地)可靠地产生大多数人通常想要的东西的唯一选项。