重载赋值运算符时返回*this的必要性、原理及非链式场景必要性咨询
关于重载赋值运算符返回
*this的那些事儿 嘿,这个问题问得特别接地气——不少刚摸C++运算符重载的朋友都会在这儿犯嘀咕,我来给你拆解清楚。
先搞懂return *this的工作机制
首先得明确:在类的成员函数里,this是指向当前调用该函数的对象的指针,而*this就是这个对象本身的左值(可以被修改的对象实例)。当我们在赋值运算符里return *this时,返回的是当前对象的左值引用——简单说就是,这个返回值直接绑定到已经完成赋值操作的对象上,不是副本,就是对象本身。
举个直观的代码例子:
class Num { private: int num; public: Num(int n = 0) : num(n) {} Num& operator=(const Num& other) { // 先做自赋值检查(避免不必要的操作,比如内存重复释放) if (this != &other) { num = other.num; } return *this; // 返回当前对象的引用 } int getNum() const { return num; } };
当你执行c = a时,调用的是c.operator=(a),函数里把a的num赋值给c的num,然后返回c的引用——也就是说,c = a这个表达式的结果就是c本身,不是新创建的Num对象。
链式赋值的核心逻辑
现在看你提到的b = d = c = a,C++里赋值运算符是右结合的,所以这个语句会从右往左拆解:
- 先执行
c = a,返回c的引用; - 接着执行
d = (c = a的结果),也就是d = c,返回d的引用; - 最后执行
b = (d = c的结果),也就是b = d,返回b的引用。
如果赋值运算符不返回*this(比如返回void),那第一步c = a的结果是void,第二步d = void就会直接编译报错——因为void类型不能作为赋值运算符的右操作数。这就是返回*this支持链式赋值的根本原因。
不用链式操作,还要返回*this吗?
答案是:非常建议返回,哪怕你现在用不上链式赋值。原因有三个:
- 遵循C++的惯例:标准库中所有的类(比如
std::string、std::vector)的赋值运算符都是返回左值引用的,保持一致的行为能让其他开发者更容易理解你的代码,也避免违反用户的直觉。 - 兼容潜在的使用场景:你现在不用链式赋值,不代表以后或者其他使用你这个类的开发者不用。如果突然需要写
if (a = b)这种(虽然有人觉得这种写法不优雅,但确实是合法的),返回void会直接报错,而返回*this就能正常工作(因为可以判断对象的状态)。 - 和默认行为对齐:编译器自动生成的默认赋值运算符,也是返回
*this的。自定义重载时保持一致,能避免出现奇怪的行为差异。
总结一下
return *this本质是返回当前被赋值的对象的左值引用,它不仅支撑了链式赋值的需求,更重要的是符合C++的设计惯例和默认行为。哪怕你暂时用不上链式操作,也最好坚持返回*this——这是一个低成本但收益很高的编码习惯。
内容的提问来源于stack exchange,提问作者maufcost
相关产品推荐
相关产品推荐

