为了理解构造函数和赋值,我写了一个非常简单的测试代码:
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
有人能解释一下我的内心发生了什么吗?
答案 0 :(得分:1)
您的运营商正在返回A
而不是A&
:
A operator=(const A &a)
因此,当您返回NULL
时,您正在调用隐式构造函数A(int)
并将NULL
传递给它。
答案 1 :(得分:1)
line 3 This is assignment operator.This is copy cstr.
您的代码致电:
A operator=(const A &a) { std::cout<<"This is assignment operator."; return *this;
这显然打印“This is assignment operator。”,然后return *this;
语句看到A
的返回类型并创建类型为A
的返回值,其值相当于{{1} } - &gt;调用复制构造函数,解释输出的这一部分:
A(*this);
但如果我改变return * this;要返回NULL,我得到了:
line 3 This is assignment operator.This is copy cstr.
^^^^^^^^^^^^^^^^^^
在这种情况下:
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为0,最好匹配A(NULL)
构造函数,这就是您看到的原因:
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&
的原因是,它允许进一步链接使用对象,如:
void
评估为:
a1 = a2 = a3;
a1.operator=(a2.operator=(a3));
返回a2.operator=
,那么void
就没有可用的参数。
非a1.operator=()
引用支持以下用法:
const
在其他一些语言中,需要将其分为两个语句。你是否希望它取决于你是否觉得它令人困惑,以及你多么重视简洁。
答案 2 :(得分:0)
您的代码说
A operator = (const A& a)
您引用了A,您自己修改,然后返回A(* this),它调用copy-constructor来创建一个新实例并按值返回。
你可能想要的是
A& operator = (const A& a)
然后会将引用返回给*this
,而不是需要将其复制到新的临时实例中。
请注意,NULL是'0UL'或'0ULL'的宏别名,编译器将其视为A(int)的匹配项。这是C ++ 11引入nullptr
作为NULL替代的原因之一。