测试程序是
#include <iostream>
using namespace std;
class A
{public:
A (): I(0) {cout << "default construcot" << endl; };
explicit A (int i): I(i) {cout << "another construcot" << endl; };
A (const A& a): I(a.I) {cout << "copy constructor" << endl; }
A& operator = (const A& a)
{cout << "assignment operator" << endl;
if (this == &a) return *this;
I = a.I;
return *this;
}
void show () {cout << I << endl; };
private:
int I;
};
int main ()
{A a = A(1);
A b;
b = A(2);
a.show();
b.show();
return 0;
}
输出
another construcot
default construcot
another construcot
assignment operator
1
2
表明,与'b'不同的对象'a'是从A(1)“直接”构造而不执行赋值运算符。但复制构造函数也没有被执行。为什么?在这种情况下,有没有办法强制执行赋值运算符?如果我写了
,我会期待这种行为A a (1);
但我想要
A a = A(1);
必须与第一种情况不同。或者不是?
(事实上,当我有一个从A派生的B类并希望A的赋值运算符处理A a = B(...)之类的声明时,会出现问题。)
答案 0 :(得分:6)
此
A a = A(1);
不等于此:
A a;
a = A(1);
在第二种情况下,=
是运算符,在第一种情况下=
不是运算符。在第一个语句中,它是一个初始化语法。编译器可以调用复制构造函数,但它可以优化它,因为它是语言允许的地方之一(RVO,异常抛出等)。
答案 1 :(得分:3)
为什么
该标准允许编译器优化复制结构。这不是 NOT 一个赋值,因为它是声明的一部分(所以如果没有进行优化,它将导致一个临时对象,然后将临时复制构造成一个)。
在这种情况下,有没有办法强制执行赋值运算符。
这取决于你的编译器。但是我不知道有什么可以让你强迫这个(但我从来没有试过把它关掉)。尝试关闭编译器正在进行的所有优化。
如果我写道:A a(1);
,我会期待这种行为
该标准明确规定您的版本可以优化为此。
我有一个从A派生的B类,并希望A的赋值运算符处理A a = B(...)之类的声明。)
如果你这样做,你将切片B并只分配B对象的A部分 你想使用参考吗?
A const& a = B();
答案 2 :(得分:1)
为什么呢?因为编译器可以自由地执行此操作,而且大部分都可以。
你可以强行吗?否。答案 3 :(得分:1)
在语言中明确定义编译器可以在任何时候基本上删除复制结构,并且第一种形式仍然是初始化语法。但是,当您使用实际派生实例调用此行为时,您可能会发现此行为已被删除,因为这样做会影响程序的正确性。
答案 4 :(得分:1)
我希望A a(1);
和A a = 1;
完全相同,标准保证。