1、Terms 10:Have assignment operators return a reference to *
关于赋值,有趣的是你可以把它们写成连锁形式,这是因为赋值运算符在每回赋值之后应该是返回“=”操作符左边的对象。如:
int x, y, z;
x = y = z = 5;
上面的“x=y=z=5”的意思是先将5赋值给z然后返回对象z,再将z对象赋值给y然后返回对象y,再将对象y赋值给对象x,最终这个表达式的结果是x。
为了实现“连锁赋值”,赋值操作符必须返回一个 reference 指向操作符的左侧实参。
class 内实现赋值操作符时应该遵循的协议:
我们建议在重载类的operator=运算符时,应该让这个运算符返回一个*this(指向于自己的类型的引用。
示例:
class Widget {
public:
Widget& operator=(const Widget& rhs)
{
return *this; //返回左侧对象
}
};
对于上面的operator=运算符,其设计规则还适用于其他辅助运算符(例如:+=、-=、*=、/=等等),例如:
class Widget {
public:
Widget& operator+=(const Widget& rhs)
{
return *this;
}
Widget& operator=(int rhs)
{
return *this;
}
};
令赋值操作运算符返回一个reference to *this。虽然这个建议不是强制性的,但是建议这么使用,例如所有内置类型和标准程序库的string、vector等都是这么遵守的。
2、面试相关
在C++中,return *this
是一个常见的模式,尤其在实现链式调用(chaining)的设计模式时。以下是关于return *this
的一些高频面试问题及其解答:
面试问题1:请解释return *this
在C++中的作用是什么?
解答:
在C++中,return *this
用于在成员函数中返回当前对象的引用。这通常用于实现链式调用,即允许在一个成员函数调用之后直接调用另一个成员函数,而无需使用中间变量。通过返回对象的引用,我们可以连续调用成员函数,从而实现更流畅、更易于阅读的代码。
面试问题2:return *this
和return this
有什么区别?
解答:
return *this
返回的是当前对象的引用(即对象本身),而return this
返回的是指向当前对象的指针。具体区别如下:
return *this
:返回对象的引用,这意味着你可以直接通过返回的引用修改对象的状态。此外,如果你返回的对象是自定义类型,那么返回引用可以避免不必要的拷贝操作,提高效率。在链式调用中,返回引用是必要的,因为你需要返回一个可以进一步调用成员函数的对象。return this
:返回指向对象的指针。虽然它也可以用于链式调用(因为指针也可以解引用并调用成员函数),但它通常不如返回引用直观和方便。此外,使用指针可能会增加出错的机会,例如空指针解引用等问题。
面试问题3:为什么在实现链式调用时通常使用return *this
而不是return this
?
解答:
链式调用的核心思想是允许我们连续调用成员函数,而不需要在每个调用之间使用中间变量。为了实现这一点,我们需要从每个成员函数中返回一个可以继续调用成员函数的对象。由于指针需要解引用才能调用成员函数,而引用可以直接调用,因此使用return *this
(即返回对象的引用)更为直观和方便。此外,返回引用还可以避免不必要的拷贝操作,提高代码效率。
面试问题4:请给出一个使用return *this
实现链式调用的例子。
解答:
以下是一个简单的例子,展示了如何使用return *this
实现链式调用:
#include <iostream>
using namespace std;
class Test {
private:
int a;
int b;
public:
Test() : a(0), b(0) {}
Test& AddA(int val) {
a += val;
return *this;
}
Test& AddB(int val) {
b += val;
return *this;
}
void Print() {
std::cout << "a: " << a << ", b: " << b << std::endl;
}
};
int main() {
Test t;
t.AddA(1).AddB(2).Print(); // 输出: a: 1, b: 2
return 0;
}
在这个例子中,AddA
和AddB
成员函数都返回*this
,这使得我们可以连续调用它们,并在最后调用Print
函数打印结果。这就是链式调用的一个简单示例。
3、总结
天堂有路你不走,地狱无门你自来。
4、参考
4.1《Effective C++》