为什么在声明对象时,构造函数和赋值运算符都没有执行?

时间:2010-12-27 19:15:07

标签: c++ oop constructor assignment-operator

测试程序是

#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(...)之类的声明时,会出现问题。)

5 个答案:

答案 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;完全相同,标准保证。