C++赋值运算符重载中&与*this的作用及必要性疑问
关于C++赋值运算符重载中引用(&)的疑问解答
首先,先把你给出的两段代码摆出来方便对比:
赋值运算符重载代码
Queue & operator=(const Queue &rhs) { front = rhs.front; nWaiting = rhs.nWaiting; for (int i = front, j = 0; j < nWaiting; j++) { elements[i] = rhs.elements[i]; i = (i + 1) % 100; } return *this; }
乘法运算符重载代码
V3 operator* (const double factor, const V3 &b) { return (b * factor); }
1. operator=前的&是什么意思?
这里的&表示这个运算符函数的返回值是Queue类型的引用,也就是说,函数返回的不是一个新的Queue对象副本,而是当前调用这个运算符的对象本身的“别名”。
2. 它和*this的配合逻辑是什么?
在C++的类成员函数里,this是一个指向当前对象的指针。*this就是对这个指针的解引用,代表当前对象的实例本身。
当我们return *this;的时候,因为函数的返回类型是Queue&,编译器会把*this(一个Queue对象)转换成它的引用——也就是返回当前对象本身,而不是拷贝一份新对象返回。
3. 为什么赋值运算符需要返回引用,而乘法运算符不需要?
这完全是由运算符的语义和使用场景决定的:
赋值运算符的需求:
- 支持链式赋值:C++的内置类型(比如
int)支持a = b = c;这样的链式赋值,为了让自定义类和内置类型保持一致的行为,赋值运算符必须返回当前对象的引用。链式赋值的本质是a = (b = c);,b = c需要返回b的引用,这样a才能直接赋值b的状态,而不是b的副本。 - 避免不必要的拷贝:如果返回值是
Queue(而非Queue&),那么return *this会调用Queue的拷贝构造函数创建一个临时对象,这会带来额外的性能开销——尤其当类的成员变量很多、拷贝成本很高的时候。返回引用则直接返回原对象,没有拷贝开销。 - 符合直观语义:赋值操作的目的是修改当前对象的状态,返回当前对象的引用,让调用者可以直接操作修改后的对象,比如
(a = b).someMethod();,这样的写法是合理的。
乘法运算符的需求:
乘法运算的语义是基于两个现有对象,生成一个新的对象(比如factor * b得到一个新的V3实例,既不修改factor也不修改b)。这时候如果返回引用,会出现两个问题:
- 如果返回局部对象的引用:函数里创建的临时对象(比如
b * factor返回的对象)在函数结束后会被销毁,返回它的引用会导致悬空引用,这是未定义行为。 - 如果返回参数的引用:比如返回
b的引用,那完全违背了乘法的语义——用户期望得到的是计算后的新对象,而不是原来的b。
所以乘法运算符返回值类型(V3)是合理的,它返回的是一个新创建的对象副本。
举个实际的例子帮你理解:
Queue a, b, c; // 初始化b和c a = b = c; // 链式赋值
如果operator=返回引用,这个过程是:
b = c调用operator=,修改b的状态,返回b的引用。a = (b的引用)调用operator=,把b的状态赋值给a,最终a、b、c状态一致。
如果operator=返回值(非引用),b = c会返回b的一个副本,然后a赋值这个副本——结果虽然一样,但多了一次Queue对象的拷贝,效率更低。
内容的提问来源于stack exchange,提问作者Rejoy Mathews
相关产品推荐
相关产品推荐

