在没有任何构造函数的类的情况下,在 C++11 中自动生成类成员函数

Posted

技术标签:

【中文标题】在没有任何构造函数的类的情况下,在 C++11 中自动生成类成员函数【英文标题】:Automatically generated class member functions in C++11 in the case of classes which do not have any constructors 【发布时间】:2014-08-07 22:05:24 【问题描述】:

在 C++11 中,我定义了以下一般形式的结构:

struct MyStruct

    static void myFunc( void );

    //constructors
    MyStruct( void ) = delete;
;

由于默认构造函数被标记为已删除,因此无法创建 MyStruct 类型的任何对象。即使myFunc 方法也无法创建该类的实例。不过该结构仍然有用,因为 MyStruct::myFuncpublic 并且可以从外部调用。

我现在的问题是:由于不可能创建任何MyStruct 类型的对象,编译器是否会费心为复制构造函数、地址运算符或析构函数创建代码?

顺便说一句:就我的实际代码而言,我确实必须根据静态类成员函数来实现功能,因为我必须利用部分模板类特化来模拟部分模板函数特化。所以我想知道如何才能让班级尽可能精简。

编辑:根据@Praetorian的评论和回答,删除了关于自动生成地址运算符的注释。

【问题讨论】:

地址操作符是什么意思?当然不是operator& - 编译器从不自动为你生成。 “所以我想知道如何让类尽可能地精简” 编译器只会为那些用于 ODR 的特殊成员函数提供定义。 我想知道是不是 UB 欺骗了编译器:std::aligned_storage<sizeof(MyStruct)>::type buffer; MyStruct obj = reinterpret_cast<MyStruct*>(&buffer); -- 因为对象没有成员,所以不应该发生左值到右值的转换。但这当然是愚蠢的/纯粹的学术性的。 @sperber 没错。 (如果你在类主体之外显式地默认一个特殊的成员函数,编译器将始终提供一个定义。但否则,只有在使用 ODR 时。) @dyp 该演员表是(目前)获得MyStruct*、default constructor deleted on its first declaration is considered trivial since it's not user-provided 的有效方式。 CWG 1496 表示这可能是语言的缺陷,但委员会尚未决定如何解决。 【参考方案1】:

编译器将为您的类隐式声明析构函数和复制构造函数,但是由于您无法创建该类的实例,因此您的程序将永远无法使用 odr-use析构函数或复制构造函数,因为它们都不会隐式定义

§12.4 [class.dtor]

4  如果类没有用户声明的析构函数,则析构函数被隐式声明为默认值 (8.4)。隐式声明的析构函数是其类的 inline public 成员。5 默认且未定义为已删除的析构函数在使用 odr 时隐式定义 (3.2)销毁其类类型 (3.7) 的对象或在其第一次声明后显式默认时。

§12.8 [class.copy]

7 如果类定义没有显式声明复制构造函数,则隐式声明。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数定义为已删除;否则,它被定义为默认值(8.4)。如果该类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。13 默认的复制/移动构造函数未定义为已删除如果它被 odr-used (3.2) 或在其第一次声明后显式默认,则被隐式定义。

至于地址运算符 (operator&),编译器永远不会为您隐式生成该运算符重载。运算符的内置地址可以应用于任何左值类型以获取其地址,但这是一种语言特性,与为用户定义类型重载该运算符无关。

【讨论】:

可以在不调用构造函数的情况下创建普通可构造类的实例,因为 [basic.life]/1 只需要对具有非普通初始化的对象进行初始化。 [class.ctor]/5 说在第一次声明时删除的默认构造函数是微不足道的。 So it's possible to ODR-use the copy/move constructors and destructor of MyStruct in a conforming - albeit ridiculously contrived - program. @Casey 哇,你真的应该把它作为答案发布......不是任何人都应该认为这样的事情是一个有效的用例:)

以上是关于在没有任何构造函数的类的情况下,在 C++11 中自动生成类成员函数的主要内容,如果未能解决你的问题,请参考以下文章

[C++11 类的改进] --- 继承构造函数和委托构造函数

[C++11 类的改进] --- 继承构造函数和委托构造函数

具有相同名称的类的构造函数继承

如何防止类中的类对象尝试在没有默认构造函数的情况下自动构建自身?

指向具有私有构造函数的类的类成员的指针

[C++11]继承构造函数