C ++默认构造函数语法

时间:2014-05-16 14:44:52

标签: c++ default-constructor

我对C ++中的默认构造函数有疑问。例如,在A类中,使用此默认构造函数A(){};A() = default;有什么区别?它们之间的一般区别是什么?

提前谢谢!

3 个答案:

答案 0 :(得分:5)

在第一个声明中定义为默认的构造函数被认为不是用户提供的。这基本上就像隐含在C ++ 03中一样。在聚合类中允许这样的构造函数声明。

struct ag {
    ag() = default;

    int a;
    double b;
};

struct nag {
    nag() {}

    int a;
    double b;
};

ag a = { 5, 12. }; // OK
nag na = { 5, 12. }; // error: not an aggregate and no appropriate constructor

此规则仅适用于班级中出现= default的情况。鉴于此类定义:

struct nag {
    nag();

    int a;
    double b;
}; 

然后这些构造函数定义确实完全等效:

nag::nag() {} // 1
nag::nag() = default; // 2

explicit默认构造函数通常禁用空副本列表初始化语法(= {})和{}作为参数或return值。聚合中的显式默认和explicit默认构造函数容易混淆地遵守此规则,因为聚合初始化具有比构造函数初始化更高的优先级。这提供了一种检测类是否为聚合的方法,但您可能不应这样做。

struct sadistic {
    explicit sadistic() = default;

    // members
};

sadistic se = {}; // OK only if sadistic has no virtual functions, etc.

答案 1 :(得分:1)

默认构造函数的行为对于每个12.1p6的A() {}A() = default;是相同的:

  

隐式定义的默认构造函数执行该类的初始化集合,该初始化集合将由该用户编写的默认构造函数执行,该类没有ctor-initializer(12.6.2)和空复合语句。

区别在于:

  • 构造函数是constexpr(显式默认的构造函数是constexpr,如果它是有效的),
  • 该类是否为聚合(8.5.1p1)和
  • 如果显式默认的默认构造函数是微不足道的(8.5p7),则值初始化是否会导致调用默认构造函数。

最后一点:

#include <iostream>

struct A { int i; A() = default; };
struct B { int j; B() {} };

int main() {
    int i = 42, j = 42;
    new (&i) A();
    new (&j) B();
    std::cout << i << std::endl;  // 0
    std::cout << j << std::endl;  // 42
}

所以你可能想要编写一个用户提供的非默认默认构造函数,例如,如果你的类具有零初始化(例如一个大数组)会很昂贵的琐碎成员,但是这是一个非常小众的案例。

答案 2 :(得分:-1)

没有太多差异:

旧语法(请注意,不需要;):

A() {}

从C ++的第一天开始就可用。它将默认构造每个基类和成员变量。

新的C ++ 11语法:

A() = default;

完全相同,但它是默认的,所以你(或编译器)不必检查大括号是否真的是空的。

请注意,如果某个类没有声明的构造函数,编译器将为您添加一个。

CORRECTION :如果删除了默认构造函数,则存在差异,即类隐式默认构造函数无效。在这种情况下,{}是语法错误,而=default就像删除的定义:

struct S
{
    int &r;  //non default constructible

    S() {} //error: uninitialized reference S::r;
    S() = default; //ok: deleted constructor
    S() = delete;  //also ok (but not both!)
};