在没有任何构造函数的类的情况下,在 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::myFunc
是 public
并且可以从外部调用。
我现在的问题是:由于不可能创建任何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 ofMyStruct
in a conforming - albeit ridiculously contrived - program.
@Casey 哇,你真的应该把它作为答案发布......不是任何人都应该认为这样的事情是一个有效的用例:)以上是关于在没有任何构造函数的类的情况下,在 C++11 中自动生成类成员函数的主要内容,如果未能解决你的问题,请参考以下文章
[C++11 类的改进] --- 继承构造函数和委托构造函数
[C++11 类的改进] --- 继承构造函数和委托构造函数