【问题标题】:Defaulted constructor vs implicit constructor默认构造函数与隐式构造函数
【发布时间】:2016-12-19 09:20:07
【问题描述】:

可能有人已经问过这个问题,但是在谷歌上搜索“默认”、“默认”、“显式”等并没有给出好的结果。但无论如何。

我已经知道显式定义的默认构造函数(即不带参数)和显式定义的默认构造函数(即使用关键字default)之间存在一些差异,来自这里:The new keyword =default in C++11

但是显式定义的默认构造函数和隐式定义的构造函数之间有什么区别(即当用户根本不编写它时)?

class A
{
public:
    A() = default;
    // other stuff
};

class A
{
    // other stuff
};

想到的一件事是,当存在非默认构造函数时,用户还必须显式定义默认构造函数。但是还有其他区别吗?

编辑:我最感兴趣的是知道是否有充分的理由编写 A() = default; 而不是完全省略构造函数(当然,假设它是该类唯一明确定义的构造函数)。

【问题讨论】:

  • Gooling for "C++ default" "C++ delete" "C++ explicit" 给出了很好的结果。你试过了吗?在进行研究时,您还应该超过三个 Google 关键字。阅读、学习、理解。
  • @LightnessRacesinOrbit 你是真的吗......这些只是例子,我没有准确地谷歌或只有这 3 个。在谷歌搜索时,例如“C++ 默认”总体上给出了一些好的结果,我没能找到关于 this exact question 的内容。

标签: c++ constructor default-constructor


【解决方案1】:

= default 的目的是使隐式定义显式。隐式定义版本和显式默认版本之间的任何差异仅限于由于存在显式声明而出现的一些额外可能性。

  1. 隐式声明/定义的构造函数始终为public,而显式定义的默认构造函数的访问控制在您自己的控制之下。

  2. 定义一个默认的默认构造函数可以让你用属性注释它。例如:

    $ cat a.cpp 
    class A
    {
    public:
        [[deprecated]] A() = default;
    };
    
    int main()
    {
        A a;
    }
    
    $ g++ -std=c++14 a.cpp
    a.cpp: In function ‘int main()’:
    a.cpp:9:7: warning: ‘constexpr A::A()’ is deprecated [-Wdeprecated-declarations]
         A a;
           ^
    a.cpp:4:20: note: declared here
         [[deprecated]] A() = default;
                        ^
    

【讨论】:

  • 当然,这是不同的。你还知道其他人吗?
  • 从我看到的所有差异来看,两个构造函数的行为似乎是相同的,但存在差异的原因是当你明确地编写它时,你可以对它做一些事情。对吗?
  • @NPS 正确。我在答案中纳入了您评论的想法。
【解决方案2】:

C++ Programming Language Stroustrup 第 4 版书的摘录清楚地表明它们是等价的。


显式默认值

由于可以抑制其他默认操作的生成,因此必须有一种方法 恢复默认值。此外,有些人更喜欢在程序中查看完整的操作列表 即使不需要完整的列表,也可以使用文本。例如,我们可以这样写:

class gslice {
    valarray<size_t> size;
    valarray<size_t> stride;
    valarray<size_t> d1;
public:
    gslice() = default;    //<< Explicit default constructor
    ~gslice() = default;
    gslice(const gslice&) = default;
    gslice(gslice&&) = default;
    gslice& operator=(const gslice&) = default;
    gslice& operator=(gslice&&) = default;
    // ...
};

这个 std::gslice (§40.5.6) 的实现片段等价于

class gslice {
    valarray<size_t> siz e;
    valarray<size_t> stride;
    valarray<size_t> d1;
public:
    // ...
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    • 2010-11-14
    相关资源
    最近更新 更多