默认构造函数与隐式构造函数
Defaulted constructor vs implicit constructor
可能有人已经问过这个问题,但谷歌搜索 "default"、"defaulted"、"explicit" 等并没有给出好的结果。但无论如何。
我已经知道显式定义的默认构造函数(即不带参数)和显式定义的默认构造函数(即带有关键字 default
)之间存在一些差异,来自此处:The new keyword =default in C++11
但是显式定义的默认构造函数和隐式定义的默认构造函数(即当用户根本不编写时)之间有什么区别?
class A
{
public:
A() = default;
// other stuff
};
对
class A
{
// other stuff
};
想到的一件事是,当存在非默认构造函数时,用户还必须显式定义默认构造函数。但是还有其他区别吗?
编辑:我最感兴趣的是知道是否有任何充分的理由编写 A() = default;
而不是完全省略构造函数(假设它是 class 的唯一明确定义的构造函数,当然)。
= default
的目的是使隐式定义显式化。隐式定义版本和显式默认版本之间的任何差异仅限于由于存在显式声明而出现的一些额外可能性。
隐式declared/defined构造函数总是public
,而显式定义的默认构造函数的访问控制由您自己控制。
定义默认的默认构造函数使您可以使用属性对其进行注释。例如:
$ 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;
^
下面摘自 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:
// ...
};
可能有人已经问过这个问题,但谷歌搜索 "default"、"defaulted"、"explicit" 等并没有给出好的结果。但无论如何。
我已经知道显式定义的默认构造函数(即不带参数)和显式定义的默认构造函数(即带有关键字 default
)之间存在一些差异,来自此处:The new keyword =default in C++11
但是显式定义的默认构造函数和隐式定义的默认构造函数(即当用户根本不编写时)之间有什么区别?
class A
{
public:
A() = default;
// other stuff
};
对
class A
{
// other stuff
};
想到的一件事是,当存在非默认构造函数时,用户还必须显式定义默认构造函数。但是还有其他区别吗?
编辑:我最感兴趣的是知道是否有任何充分的理由编写 A() = default;
而不是完全省略构造函数(假设它是 class 的唯一明确定义的构造函数,当然)。
= default
的目的是使隐式定义显式化。隐式定义版本和显式默认版本之间的任何差异仅限于由于存在显式声明而出现的一些额外可能性。
隐式declared/defined构造函数总是
public
,而显式定义的默认构造函数的访问控制由您自己控制。定义默认的默认构造函数使您可以使用属性对其进行注释。例如:
$ 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; ^
下面摘自 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:
// ...
};