C++类的隐式默认构造函数

昨天同事问我为什么他的类似下面的代码编译不过(VC2010):

class Robbin
{
};

class Batman
{
private:
    Robbin& assistant;

}; 

编译错误是:error C2512: 'Batman' : no appropriate default constructor available。从错误上来看很明显,编译器没有为Batman隐式生成默认构造函数。但是为什么没有生成呢?一开始没反应过来,几分钟后才想到是引用造成的。但是新的问题又来了,为什么编译错误不是error C2530: 'assistant' : references must be initialized ? 于是决定重温下C++类的隐式默认构造函数的生成规则。Google了一下,答案好像都是说了个大概但并不完全。而且还有一些奇怪的翻译:"对于类X,如果没有任何用户定义的构造函数,那么就会有一个默认构造函数被暗自声明出来;这种函数一般没有什么用。。。";"其实默认构造函数也是分为两类的:有用的、无用的。" 汗,这里trivial/non-trivial难道不是平凡/非平凡?为什么默认的就没有用啊....总体来说,答案都基于标准14882和XL C/C++ V8.0 for AIX的文档:

14882:2003 - 12.1.5, 12.1.6

A constructor is trivial if it is an implicitly-declared default constructor and if:
- its class has no virtual functions (10.3) and no virtual base classes (10.1), and
- all the direct base classes of its class have trivial constructors, and
- for all the nonstatic data members of its class that are of class type (or array thereof), each such class has a trivial constructor.

Otherwise, the constructor is non-trivial.

从标准看,有一个引用成员并不会影响隐式默认构造函数的生成。XL C/C++的倒是提到了:No default constructor is created for a class that has any constant or reference type members. 难道这不是标准仅是各编译器约定的行为?于是又去找了C++11的标准(新浪iask资料果然多啊),发现新标准的12.1.5增加了不少内容:

14882:2011 12.1.5

 A defaulted default constructor for class X is defined as deleted if:

......

- any non-static data member with no brace-or-equal-initializer is of reference type

any non-variant non-static data member of const-qualified type (or array thereof) with no brace-orequal-initializer does not have a user-provided default constructor

...... 

可以看到 XL C/C++ V8.0 for AIX里提到的那句话在最新标准里已经有规定。所以这个问题的终极答案:对于旧标准,这种情况的处理规则没有做出规定,但是至少VC2010和XL C/C++不会为其隐式生成默认构造函数。对于新标准,因为Batman里定义了一个引用类型的成员而且也没有大括号或等号形式的初始化器(貌似也没法做到?),所以根据12.1.5编译器会把默认构造函数标注成deleted,逻辑意义上也就相当于没有生成了。

原文地址:https://www.cnblogs.com/shawnhue/p/2264416.html