首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么删除复制构造函数会影响用户定义的默认构造函数?

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

Stack Overflow用户
提问于 2017-09-15 17:05:44
回答 3查看 131关注 0票数 2

学习C++,很少有关于构造函数的问题。

请考虑以下代码:

代码语言:javascript
复制
#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 bar1 = CBar();一样创建一个CBar bar1 = CBar();实例
  2. testFoo调用4个析构函数。其中3种为foo0、foo1和foo2。第四个从何而来?testBaz具有相同的结构,但只调用3个析构函数。CFooCBaz之间唯一的区别是CBaz具有用户定义的复制构造函数。
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-09-15 17:10:20

  1. 为什么我不能像CBar bar1 = CBar();一样创建一个CBar bar1 = CBar();实例

删除CBar的复制构造函数。因此,CBar是不可复制的。因此,不能复制初始化CBar

CFoo是可以复制的,所以没有问题。

CBar bar1 = CBar();//为什么这与复制构造函数有任何关系?

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

  1. 第四是哪里来的?

除了命名对象(变量),还有两个临时对象,CFoo()CFoo(foo1)。无论出于什么原因,只有其中一位临时人员通过复制筛选而被优化。

testBaz具有相同的结构,但只调用3个析构函数。

这在某种程度上影响了操作系统。我看不出为什么两个CFoo`临时代码都不可能被优化掉,但是其中一个没有被优化,因为我的编译器确实对两者进行了优化。

PS。CBaz baz1 = CBaz();格式不正确,因为非const值引用不能绑定到临时引用。

PPS。void main()格式错误,因为main必须返回int

票数 2
EN

Stack Overflow用户

发布于 2017-09-15 17:15:43

CBar bar1 = CBar();不是分配,而是使用复制/移动构造函数进行初始化。

即使被省略,移动/复制构造函数也应该是可访问的。

由于使用了保护省略的C++17,规则已经改变,而且CBar bar1 = CBar();不要求移动/复制构造函数是可访问的,它相当于CBar bar1{};

票数 2
EN

Stack Overflow用户

发布于 2017-09-15 17:11:05

这是直接初始化:

代码语言:javascript
复制
CFoo foo0;

这是副本初始化:

代码语言:javascript
复制
CBaz baz1 = CBaz();

由于https://en.wikipedia.org/wiki/Copy_elision,复制初始化在性能上等同于直接初始化,而在语义上则不然;复制初始化仍然需要一个可访问的副本构造函数。

四个析构函数输出中有两个来自用CFoo的默认复制构造函数构造的实例。注意,打印的数量取决于优化:当复制省略优化打开时,对中间情况(即CFoo foo1 = CFoo() )的复制构造函数的调用可以优化出来,因此可以得到三个输出,而不是四个。CFoo foo2 = CFoo(foo0)右侧的副本没有优化。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46244513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档