我写了下面程序来测试当复制构造函数被调用,并且当赋值运算符被称为:


#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
This is the default ctor
This is the copy ctor
This is the dtor
This is the dtor

This is the default ctor
This is the copy ctor
This is the dtor
This is the dtor

This is the default ctor
This is the default ctor
This is the assignment operator
This is the dtor
This is the dtor


如预期的第二和第三组的行为,但在第一组即使赋值运算符是用来复制构造被调用。

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

有帮助吗?

解决方案

没有赋值运算符在第一测试例中使用。它只是使用了所谓的“拷贝初始化”初始化形式。初始化对象时拷贝初始化不考虑显式的构造。

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

复制初始化将在对应于隐式转换,其中,一个没有明确踢掉转换,如在函数参数传递的那些情况下使用,并且从函数返回。

其他提示

C ++标准的8.5 / 12

  

这发生在初始化   参数传递,函数返回,   抛出一个异常(15.1),处理   一个异常(15.3),和   括号内的初始化列表   (8.5.1)被称为副本初始化   和相当于形式

T x = a;
     

这发生在新的初始化   式(5.3.4),的static_cast   式(5.2.9),功能   符号类型转换(5.2.3),和   基和成员初始化(12.6.2)   被称为直接初始化,并   相当于形式

T x(a);

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

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

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);

最后一行将是一个符合的情况。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top