【问题标题】:C++ overriding the assignment operatorC++ 重写赋值运算符
【发布时间】:2013-11-09 11:03:35
【问题描述】:

为了理解构造函数和赋值,我写了一个非常简单的测试代码,如下所示:

class A {
public:
    A() { std::cout<<"This is default cstr."; }
    A(int i) { std::cout<<"This is int cstr. value is "<<i; }
    A(const A &a) { std::cout<<"This is copy cstr."; }
    A operator=(const A &a) { std::cout<<"This is assignment operator."; return *this;// this line is tricky }
};
int _tmain(int argc, _TCHAR* argv[]) {
    std::cout<<"line 1 "; A a1; std::cout<<std::endl;
    std::cout<<"line 2 "; A a2 = A(1); std::cout<<std::endl;
    std::cout<<"line 3 "; a1 = a2; std::cout<<std::endl;
    return 0;
}

对于第 3 行,我得到了:

line 3 This is assignment operator.This is copy cstr.

但如果我将return *this; 更改为return NULL,我得到:

line 3 This is assignment operator.This is int cstr. value is 0

谁能为我解释一下里面发生了什么?

【问题讨论】:

    标签: c++ constructor variable-assignment operator-keyword


    【解决方案1】:

    您的操作员返回的是A,而不是A&amp;

    A operator=(const A &a)
    

    因此,当您返回 NULL 时,您正在调用隐式构造函数 A(int) 并将 NULL 传递给它。

    【讨论】:

    • 谢谢!那么每个非引用返回都会调用一次副本 cstr 吗?
    • 不,你没有抓住重点。赋值运算符应该返回一个引用。并且引用不能为 NULL。您应该将A(int) 构造函数声明为explicit A(int),编译器会产生错误。你得到的行为几乎总是由于一个无意的错误。
    【解决方案2】:

    你的代码说

    A operator = (const A& a)
    

    您引用一个 A,修改自己,然后返回 A(*this),它调用复制构造函数来创建一个新实例并按值返回。

    你可能想要的是

    A& operator = (const A& a)
    

    这将返回一个引用*this,而不是需要将它复制到一个新的临时实例中。

    请注意,NULL 是“0UL”或“0ULL”的宏别名,编译器将其检测为与 A(int) 匹配。这也是 C++11 引入 nullptr 来替代 NULL 的原因之一。

    【讨论】:

      【解决方案3】:

      问题

      line 3 This is assignment operator.This is copy cstr.
      

      您的代码调用:

      A operator=(const A &a) { std::cout<<"This is assignment operator."; return *this;
      

      这显然会打印“这是赋值运算符。”,然后return *this; 语句看到A 的返回类型并创建一个A 类型的返回值,相当于A(*this); -> 调用副本构造函数,解释这部分输出:

      line 3 This is assignment operator.This is copy cstr.
                                         ^^^^^^^^^^^^^^^^^^
      

      但是如果我改变返回 *this;要返回 NULL,我得到了:

      line 3 This is assignment operator.This is int cstr. value is 0
      

      在这种情况下:

      A operator=(const A &a) { std::cout<<"This is assignment operator."; return NULL; }
      

      您最终会根据 A(NULL) 创建类型为 A 的返回值,并且由于 NULL 为 0,这与 A(int) 构造函数最匹配,这就是您看到的原因:

      line 3 This is assignment operator.This is int cstr. value is 0
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      

      解决方案

      A& operator=(const A &a) { std::cout<<"This is assignment operator."; return *this; }
       ^
      

      您通常希望赋值运算符返回对*this 对象的引用。这样,在赋值运算符函数返回时,不会构造额外的 A 对象。

      除此之外 - 为什么要返回 `A&`?

      返回 A&amp; 而不是 void 的原因是它允许进一步链式使用对象,如下所示:

      a1 = a2 = a3;
      

      评估为:

      a1.operator=(a2.operator=(a3));
      

      如果a2.operator= 返回了void,那么a1.operator=() 将没有可用的参数。

      const 引用支持如下用法:

      make_uppercase(my_string = other_string);
      

      在其他一些语言中,这需要分成两个语句。你是否希望它取决于你是否觉得它令人困惑,以及你对简洁的重视程度。

      【讨论】:

        猜你喜欢
        • 2013-03-30
        • 2016-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-27
        • 2011-07-29
        • 1970-01-01
        相关资源
        最近更新 更多