operator=为什么要返回一个reference to *this

来源:互联网 发布:怀化网络家教招聘 编辑:程序博客网 时间:2024/06/05 06:35

一、 函数返回值

说到operator=的返回值,那么先必须要说一下函数的返回值。函数的返回值用于初始化在调用函数处创建的临时对象,函数的返回值分值类型和引用类型。

1、 返回值类型

      返回值类型, 即告诉编译器在调用函数处创建的临时对象是函数返回对象的一个值类型。

      Test Fun() {

            Test a;

            return a;

      }

      Test a = Fun();

      则经过编译器处理后伪代码大致如下:

      Test termporary = Fun();  -------这里通过Test的拷贝构造函数来初始化这个临时对象实例

      Test a = termporary;  ------这里再用termporary通过拷贝构造来初始化a

      termporary.~Test();---------释放掉此临时对象

      或者经过编译器优化为:

      Test a = Fun();  -------这里通过Test的拷贝构造函数直接初始化对象实例a,即没有临时对象。


2、返回引用类型

     返回引用类型, 即告诉编译器在调用函数处创建的临时对象是函数返回对象的一个引用。

     Test& Fun() {

            static Test a;
            return  a;

      }

     Test b = Fun();

     则经过编译器处理后伪代码大致如下:

     Test& termporary = Fun();  -------创建Fun的返回对象实例a的引用termporary

     Test b = termporary;  ------这里再用termporary通过拷贝构造来初始化b

    

     但是如果通过形如Test& a = Fun();来调用函数呢?经过编译器处理后伪代码大致如下:

     Test& termporary = Fun();  -------创建Fun的返回对象实例a的引用termporary

     Test &b = termporary;  ------b为termporary的引用,即为Fun的返回对象实例a的别名

    注:

   函数返回引用类型,其实就是返回了一个真实对象的一个别名(返回的对象termporary就是真实对象的一个别名)


二、operator=返回值

      <<Effective C++>>中说到 operator=必须要返回一个reference to *this,为什么呢? 他给出的理由是 Test a, b, c; a = b = c;  为了实现这种“连锁赋值”。 那么真的如书上所说的如果不返回引用类型就无法实现上述“连锁赋值”吗? 其实不然。

class Test{public:    Test() {  };     Test(int i) { number = i; };     ~Test( ) { };     Test(const Test& p){ number = p.number; };    Test operator=(const Test& p) {number = p.number; return *this;};  public:    void DoSomething() {cout << "My test" << endl; };public:    int number;};
如上代码,Test 的operator=返回的不是引用类型,但是照样能实现a = b = c;这种“连锁赋值”。只是比operator=返回的是引用类型情况下多调用两次copy构造函数。 a = b = c;被解析为 a = (b = c), 那么b = c时返回值必须通过copy构造函数来初始化临时对象termporary。 然后termporary通过操作符号operator=赋值给a,即a = termporary, operator=返回时同样会调用copy构造函数来初始化另外一个临时对象。故多调用两次copy构造函数而已。

所以,只是说从效率上来说, operator=返回引用比返回值类型要高效。

另外, 如果想要支持另外一种“连锁赋值”,如 (a = b) = c; 那么就必须要operator=返回引用类型。即 a = b 返回的是 a的一个引用类型临时对象termporary,那么将c赋值给这个a的引用,即可正确地实现表达式的含义。 如果operator=返回值类型呢? 那么a = b 返回的是a的一个值类型临时对象termporary, 那么c赋值给这个临时对象termporary后,根本没有改变a的值,也就没有正确地实现表达式的含义。

所以,综上两点, operator=还是老老实实地返回一个reference to *this吧。


0 0
原创粉丝点击