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

为什么删除复制构造函数会影响用户定义的默认构造函数?

  •  2
  • AlexXsWx  · 技术社区  · 7 年前

    学习C++时,对于构造函数几乎没有问题。

    请考虑以下代码:

    #include<stdio.h>
    #include<iostream>
    
    // Case 1
    
    class CFoo
    {
    public:
        CFoo()  { printf("CFoo constructor: user-defined default\n"); }
        ~CFoo() { printf("CFoo destructor\n"); }
    };
    
    void testFoo()
    {
        CFoo foo0;              // A way to use default constructor
        CFoo foo1 = CFoo();     // Another way to use default constructor
        CFoo foo2 = CFoo(foo1); // Using implicit copy constructor
    
        // Output:
        //     CFoo constructor: user-defined default
        //     CFoo constructor: user-defined default
        //     CFoo destructor
        //     CFoo destructor
        //     CFoo destructor
        //     CFoo destructor
    }
    
    // Case 2
    
    class CBar
    {
    public:
        CBar() { printf("CBar constructor: user-defined default\n"); }
        CBar(CBar & other) = delete;
        ~CBar() { printf("CBar destructor\n"); }
    };
    
    void testBar()
    {
        CBar bar0;
        // line 44: error C2280: 'CBar::CBar(CBar &)': attempting to reference a deleted function
        // line 34: note: see declaration of 'CBar::CBar'
        // line 34: note: 'CBar::CBar(CBar &)' : function was explicitly deleted
        // CBar bar1 = CBar(); // Why this has anything to do with the copy constructor?
    
        // Output:
        //     CBar constructor: user-defined default
        //     CBar destructor
    }
    
    // Case 3
    
    class CBaz
    {
    public:
        CBaz()             { printf("CBaz constructor: user-defined default\n"); }
        CBaz(CBaz & other) { printf("CBaz constructor: user-defined copy\n"); }
        ~CBaz()            { printf("CBaz destructor\n"); }
    };
    
    void testBaz()
    {
        CBaz baz0;
        CBaz baz1 = CBaz();
        CBaz baz2 = CBaz(baz1);
    
        // Output:
        //     CBaz constructor: user-defined default
        //     CBaz constructor: user-defined default
        //     CBaz constructor: user-defined copy
        //     CBaz destructor
        //     CBaz destructor
        //     CBaz destructor
    }
    
    // main
    
    void main() {
        testFoo();
        testBar();
        testBaz();
    
        std::cin.get();
    }
    

    问题:

    1. 为什么我无法创建的实例 CBar CBar bar1 = CBar(); 就像我做的那样 CFoo ?

    2. testFoo 调用4个析构函数。其中3个用于foo0、foo1和foo2。第四名来自哪里? testBaz 具有相同的结构,但仅调用3个析构函数。唯一的区别是 CBaz 是吗 具有用户定义的副本构造函数。

    3 回复  |  直到 7 年前
        1
  •  2
  •   eerorika    7 年前
    1. 为什么我无法创建的实例 CBar CBar bar1 = CBar(); 就像我做的那样 CFoo

    的复制构造函数 CBar 已删除。因此 CBar .

    CBar bar1 = CBar(); // Why this has anything to do with the copy constructor?
    

    T object = other; 是复制初始化的语法。


    1. 第四名来自哪里?

    CFoo() CFoo(foo1) . 无论出于何种原因,只有一个临时版本通过复制省略进行了优化。

    testBaz

    这在某种程度上影响了opimizer。我看不出为什么两个CFoo的临时对象都不能被优化掉,但有一个没有。值得一提的是,我的编译器对这两个都进行了优化。


    附言 CBaz baz1 = CBaz();

    void main() 格式不正确,因为 main 必须返回 int

        2
  •  2
  •   Jarod42    7 年前

    CBar bar1 = CBar(); 不是赋值,而是使用复制/移动构造函数的初始化。

    CBar bar1=CBar(); 这相当于 CBar bar1{};

        3
  •  1
  •   Sergey Kalinichenko    7 年前

    这是直接初始化:

    CFoo foo0;
    

    这是复制初始化:

    CBaz baz1 = CBaz();
    

    copy elision

    四个析构函数打印输出中有两个来自使用的默认副本构造函数构造的实例 CFoo . 请注意,打印输出的数量取决于优化:当“复制省略优化”处于启用状态时,将为中间情况调用复制构造函数,即。 CFoo foo1 = CFoo() 可以优化输出,因此可以得到三个打印输出,而不是四个。副本位于 CFoo foo2 = CFoo(foo0) 未优化。