3

我编写了以下程序来测试何时调用复制构造函数以及何时调用赋值运算符:


#include 

class Test
{
public:
    Test() :
        iItem (0)
    {
        std::cout << "This is the default ctor" << std::endl;
    }

    Test (const Test& t) :
        iItem (t.iItem)

    {
        std::cout << "This is the copy ctor" << std::endl;
    }

    ~Test()
    {
        std::cout << "This is the dtor" << std::endl;
    }

    const Test& operator=(const Test& t)
    {
        iItem = t.iItem;    
        std::cout << "This is the assignment operator" << std::endl;
        return *this;
    }

private:
    int iItem;
};

int main()
{
    {
        Test t1;
        Test t2 = t1;
    }
    {
        Test t1;
        Test t2 (t1);
    }
    {
        Test t1;
        Test t2;
        t2 = t1;
    }
}

这会产生以下输出(只是添加了 empy 行以使其更易于理解):

doronw@DW01:~$ ./test
这是默认的ctor
这是复制ctor
这是dtor
这是dtor

这是默认的ctor
这是复制ctor
这是dtor
这是dtor

这是默认的ctor
这是默认的ctor
这是赋值运算符
这是dtor
这是dtor


第二组和第三组按预期运行,但在第一组中,即使使用了赋值运算符,也会调用复制构造函数。

这种行为是 C++ 标准的一部分还是只是一个聪明的编译器优化(我使用的是 gcc 4.4.1)

4

3 回答 3

10

在第一个测试用例中没有使用赋值运算符。它只是使用称为“复制初始化”的初始化形式。初始化对象时,复制初始化不考虑显式构造函数。

struct A {
  A();

  // explicit copy constructor
  explicit A(A const&);

  // explicit constructor
  explicit A(int);

  // non-explicit "converting" constructor
  A(char const*c);
};

A a;
A b = a; // fail
A b1(a); // succeeds, "direct initialization"

A c = 1; // fail, no converting constructor found
A d(1); // succeeds

A e = "hello"; // succeeds, converting constructor used

复制初始化用于与隐式转换相对应的情况,在这种情况下,不会显式启动转换,如函数参数传递和从函数返回。

于 2010-01-08T13:45:28.130 回答
3

C++ 标准 8.5/12

在参数传递、函数返回、抛出异常 (15.1)、处理异常 (15.3) 和大括号括起来的初始化列表 (8.5.1) 中发生的初始化称为复制初始化,等效于形式

T x = a;

在 new 表达式 (5.3.4)、static_cast 表达式 (5.2.9)、函数符号类型转换 (5.2.3) 以及基和成员初始化程序 (12.6.2) 中发生的初始化称为直接初始化,等效于表格

T x(a);
于 2010-01-08T13:57:24.463 回答
2

您的第一组是根据 C++ 标准,而不是由于一些优化。

C++ 标准的12.8 ( [class.copy])节给出了一个类似的例子:

class X {
    // ...
public:
    X(int);
    X(const X&, int = 1);
};

X a(1);     // calls X(int);
X b(a, 0);  // calls X(const X&, int);
X c = b;    // calls X(const X&, int);

最后一行将与您的情况相匹配。

于 2010-01-08T13:50:26.020 回答