五法则和隐式删除的函数 [duplicate]

rule of five and implicitly deleted functions [duplicate]

提问人:Elimination 提问时间:9/25/2017 更新时间:9/25/2017 访问量:3225

问:

根据我的理解,五法则是一个指导规则。尽管如此,我已经看到编译器在某些情况下可能会隐式删除函数。例如,在定义 move-ctor' 时,将删除复制分配/复制 ctor'。

我想知道是否还有更多提到的场景。换言之,在哪些场景下,用户自定义函数可以隐式删除其他函数?

谢谢

编辑:
引用涵盖该主题的一些来源也可以!

C++ C++11 三法则

评论

0赞 Kerrek SB 9/25/2017
只有三个特殊成员始终声明,如果不是用户声明,则隐式声明:复制构造函数、复制赋值和析构函数。如果操作不可用,则其每个隐含声明都可能是已删除的声明。
0赞 StoryTeller - Unslander Monica 9/25/2017
所有这些都包含在C++标准的“特殊成员函数”下。只需在该部分中查找“已删除”一词即可。
1赞 MikeMB 9/25/2017
在某个地方有一个关于这个的 nixe 矩阵(可能是某个会议上演讲的一部分),但为了上帝的爱,我找不到正确的知道。
1赞 aschepler 9/25/2017
@MikeMB stackoverflow.com/a/24512883/459640
0赞 aschepler 9/25/2017
请注意,在某些情况下,声明已删除的函数(可以通过重载解析找到,但随后失败)和根本不声明函数(重载解析不会看到)之间存在差异。

答:

4赞 nyronium 9/25/2017 #1

对于所有“五”,该标准定义了在何种情况下它们将被隐含地宣布为删除。我已经为您命名并引用了 C++ 标准 N4659 中的相关部分:

  • (12.3.3) 在定义联合时,可以隐式删除以下五项中的一些:

    [..][ 注意:缺席默认成员 初始值设定项 (12.2),如果联合的任何非静态数据成员具有非平凡的默认构造函数 (15.1),请复制 构造函数 (15.8), 移动构造函数 (15.8), 复制赋值运算符 (15.8), 移动赋值运算符 (15.8), 或析构函数 (15.4),则联合的相应成员函数必须由用户提供,否则将是 隐式删除 (11.4.3) for the union — end note ]

  • (15.1) 当没有用户定义的替代方案时,隐式声明了“五”:

    默认构造函数 (15.1)、复制构造函数和复制赋值运算符 (15.8)、移动构造函数 移动赋值运算符 (15.8) 和析构函数 (15.4) 是 特殊成员功能 .[ 注意: 这 当程序不这样做时,实现将为某些类类型隐式声明这些成员函数 显式声明它们。如果使用 odr (6.2),则实现将隐式定义它们。见 15.1, 15.4 和 15.8。 — 尾注 ]

  • (15.1.1) 隐式删除构造函数:

    在以下情况下,类 X 的默认默认构造函数定义为已删除:
    — (5.1) X 是一个联合,它有一个具有非平凡默认构造函数的变体成员,并且 X 的变体成员没有默认成员初始值设定项, — (5.2) X 是一个非联合类,它有一个具有非平凡默认构造函数的变体成员 M,并且包含 M 的匿名联合的变体成员没有默认成员初始值设定项,

    — (5.3) 任何没有默认成员初始值设定项 (12.2) 的非静态数据成员都是引用类型, — (5.4) 任何没有大括号或等于初始值设定项的 const 限定类型(或其数组)的非变体非静态数据成员都没有用户提供的默认构造函数, — (5.5) X 是一个联合,

    它的所有变体成员都是 const 限定的类型(或其数组),
    — (5.6) X 是一个非联合类,任何匿名联合成员的所有成员都是 const 限定类型(或其数组), — (5.7) 任何可能构造的子对象,除了带有大括号或等号初始值设定项的非静态数据成员外,都具有类类型 M(或其数组),
    并且 M 没有默认构造函数或重载解析 (16.3) 应用于查找 M 的相应构造函数会导致歧义或函数被删除或无法访问从默认的默认构造函数,或者
    — (5.8) 任何可能构造的子对象都具有具有析构函数的类型,该析构函数已从默认默认构造函数中删除或无法访问

  • (15.8.1.10) 隐式删除复制/移动构造函数:

    类 X 的默认复制/移动构造函数定义为已删除 (11.4.3),如果 X 具有:
    — (10.1) 具有非平凡对应构造函数的变体成员,并且 X 是一个类似联合的类, — (10.2) 一个可能构造的子对象类型 M(或其数组),由于重载解析 (16.3) 而无法复制/移动,用于查找 M 的相应构造函数,
    导致歧义或函数被删除或无法从默认构造函数访问,
    — (10.3) 具有析构函数的任何潜在构造子对象,该子对象具有从默认构造函数中删除或无法访问的析构函数,或者
    — (10.4) 对于复制构造函数,是右值引用类型的非静态数据成员。重载解析 (16.3, 16.4) 将忽略定义为已删除的默认移动构造函数。[ 注意:删除的移动构造函数会干扰右值的初始化,而右值可以改用复制构造函数。

  • (15.8.2) 隐式删除复制/移动赋值运算符:

    如果 X 具有以下条件,则类 X 的默认复制/移动赋值运算符定义为删除:
    — (7.1) 具有非平凡的相应赋值运算符的变体成员,并且 X 是类似联合的类,或者
    — (7.2) 常量非类类型(或其数组)的非静态数据成员,或 — (7.3) 引用类型的非静态数据成员,或

    — (7.4) 类类型 M(或其数组)的直接非静态数据成员或无法复制/移动的直接基类 M,因为重载解析 (16.3) 应用于查找 M 的相应赋值运算符会导致歧义或函数被删除或无法从默认赋值运算符访问。

  • (15.4.5) 隐式删除析构函数:

    在以下情况下,类 X 的默认析构函数被定义为删除:
    — (5.1) X 是一个类似联合的类,它有一个具有非平凡析构函数的变体成员, — (5.2) 任何可能构造的子对象都具有类类型 M(或其数组),并且 M 具有已删除的析构函数或默认析构函数无法访问的析构函数,

    — (5.3) 或者,对于虚拟析构函数,查找非数组释放函数会导致歧义或函数被删除或无法从默认析构函数访问。