1

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

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

有人可以为我解释一下里面发生了什么吗?

4

3 回答 3

1

您的运营商正在返回A而不是A&

A operator=(const A &a)

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

于 2013-10-30T02:23:07.477 回答
1

问题

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.
                                   ^^^^^^^^^^^^^^^^^^

但是如果我改变 return *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; }

您最终创建了Aas per类型的返回值A(NULL),并且 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&返回而不是返回的原因是void它允许进一步链式使用该对象,如:

a1 = a2 = a3;

评估为:

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

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

const参考支持如下用法:

make_uppercase(my_string = other_string);

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

于 2013-10-30T02:32:11.490 回答
0

你的代码说

A operator = (const A& a)

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

你可能想要的是

A& operator = (const A& a)

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

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

于 2013-10-30T02:28:11.703 回答