编译器何时为类的特殊成员提供定义?
Posted
技术标签:
【中文标题】编译器何时为类的特殊成员提供定义?【英文标题】:When does the compiler provide definitions for the special members of a class? 【发布时间】:2012-01-27 02:36:13 【问题描述】:我知道,当我定义一个空类并且根本不提供任何声明时,编译器会为默认和复制构造函数、析构函数和复制赋值运算符提供定义。
这有什么规则?编译器何时不提供复制构造函数?移动构造函数和移动赋值运算符呢?
(例如:如果我的类有 int&
这样的引用成员,编译器将不会为任何赋值运算符提供定义。其他什么时候会发生这种情况?)
【问题讨论】:
@Mr.TAMER:***很好,但我想有一个完整的 SO 列表,最好是标准引号。 :) 此外,***文章没有说明何时获得移动构造函数以及何时不提供复制 ctor / 赋值操作。 会不会不提供赋值运算符,即使你有引用成员。尝试使用它会生成编译,不是因为它不存在,而是因为它无效。 在不输入标准第 12 章的大量内容的情况下,我们应该如何回答这个问题?这一切都在那里,它是标准中非常明确的一部分。 “我知道,当我定义一个空类并且根本不提供任何声明时,编译器将提供默认和复制构造函数、析构函数和复制赋值运算符的定义。”。这是不正确的。它只会提供这些的声明。并且定义仅在需要时使用。 @Xeo 不,这些不是形式。如果你有struct A void operator=(int); operator int(); int &x; ; A a*new int, b*new int;
,如果你说a = b;
,它会给出一个错误,因为它确实提供了复制分配的声明。如果不是,它不是是一个错误,但它会将b
转换为int
。
【参考方案1】:
编辑:在 C++11 中,它比隐式声明或不隐式声明更复杂。它们可以被隐式声明和默认,隐式声明和删除,或未声明。阅读this以区分后者2。以下信息并不完全正确,因为它不区分已声明和已删除与未声明。
以下是正在进行的工作。 (?)
表示我想澄清或量化该声明。
特殊成员函数 §12/1
当用户没有显式声明它们时,实现会为某些类类型隐式声明这些成员函数:
默认构造函数 复制构造函数 复制赋值运算符 移动构造函数 移动赋值运算符 析构函数如果类型有一个特殊的成员函数,则不会隐式声明...
默认构造函数§12.1/5
复制构造函数§12.8/8, §12.8/12
用户声明的移动构造函数 用户声明的移动赋值运算符 右值引用类型的非静态数据成员 具有非平凡复制构造函数的变体成员并且是类联合类 (?) 无法复制的类型(或其数组)的非静态数据成员 没有可访问复制构造函数的直接或虚拟基类*如果类具有用户声明的复制赋值运算符或用户声明的析构函数 (?),则不推荐使用此类隐式声明
复制赋值运算符§12.8/19, §12.8/24
用户声明的移动构造函数 用户声明的移动赋值运算符 具有非平凡复制赋值运算符的变体成员,是类联合类 (?) const 非类类型(或其数组)的非静态数据成员 引用类型的非静态数据成员 具有不可访问的复制赋值运算符的非静态数据成员 具有不可访问的复制赋值运算符的直接或虚拟基类*如果类具有用户声明的复制构造函数或用户声明的析构函数 (?),则不推荐使用此类隐式声明
移动构造函数§12.8/10, §12.8/12
用户声明的复制构造函数 用户声明的复制赋值运算符 用户声明的移动赋值运算符 用户声明的析构函数 移动构造函数不会被隐式定义为已删除 (?) variant 成员具有非平凡的移动构造函数并且是类联合类 (?) 不能移动的类型(或其数组)的非静态数据成员 非静态数据成员或直接或虚拟基类,其类型没有移动构造函数且不可轻易复制 没有可访问的移动构造函数的直接或虚拟基类移动赋值运算符§12.8/21, §12.8/24
用户声明的复制构造函数 用户声明的移动构造函数 用户声明的复制赋值运算符 用户声明的析构函数 移动赋值运算符不会被隐式定义为已删除 (?) 具有非平凡移动赋值运算符的变体成员,是类联合类 (?) const 非类类型(或其数组)的非静态数据成员 引用类型的非静态数据成员 具有不可访问的移动赋值运算符且不可轻易复制的非静态数据成员 具有不可访问的移动赋值运算符且不可轻易复制的直接或虚拟基类析构函数§12.4/4
【讨论】:
以上是关于编译器何时为类的特殊成员提供定义?的主要内容,如果未能解决你的问题,请参考以下文章