代码之家  ›  专栏  ›  技术社区  ›  doron

复制构造函数和赋值运算符

  •  3
  • doron  · 技术社区  · 14 年前

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

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

    3 回复  |  直到 14 年前
        1
  •  10
  •   Johannes Schaub - litb    14 年前

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

    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
    

    复制初始化用于那些与隐式转换相对应的情况,其中没有显式启动转换,如函数参数传递和从函数返回。

        2
  •  3
  •   Andreas Brinck    14 年前

    C++标准85/12

    在中发生的初始化 参数传递,函数返回, 抛出异常(15.1),处理 例外情况(15.3),以及 括号括起的初始值设定项列表 (8.5.1)称为拷贝初始化 相当于形式

    T x = a;
    

    在新的 表达式(5.3.4),静态 表达式(5.2.9),功能性 符号类型转换(5.2.3),以及 基本和成员初始值设定项(12.6.2) 被称为直接初始化 相当于形式

    T x(a);
    
        3
  •  2
  •   stakx - no longer contributing Saravana Kumar    14 年前

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

    第12.8节( [class.copy] C++ standard 举了一个类似的例子:

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

    最后一行是与您的案件相匹配的那一行。