5

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

我想知道是否还有上述情况。也就是说,用户自定义函数在哪些场景下可以隐式删除其他函数?

谢谢

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

4

1 回答 1

4

对于所有“五”,标准定义了它们将被隐式声明为删除的情况。我已经为您命名并引用了 C++ 标准N4659中的相关部分:

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

    [..] [注意:缺少默认成员初始化程序(12.2),如果联合的任何非静态数据成员具有非平凡的默认构造函数(15.1),复制构造函数(15.8),移动构造函数(15.8),复制赋值运算符(15.8),移动赋值运算符(15.8)或析构函数(15.4),联合的相应成员函数必须是用户提供的,否则它将被隐式删除(11.4.3)联合 - 尾注]

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

    默认构造函数 (15.1)、复制构造函数和复制赋值运算符 (15.8)、移动构造函数和移动赋值运算符 (15.8) 和析构函数 (15.4) 是特殊的成员函数。[注意:当程序没有显式声明它们时,实现将为某些类类型隐式声明这些成员函数。如果它们被 odr-used (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 具有以下条件,则类 X 的默认复制/移动构造函数定义为已删除 (11.4.3):
    - (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) 非const 非类类型(或其数组)的静态数据成员,或
    — (7.3) 引用类型的非静态数据成员,或
    — (7.4) 类类型 M(或其数组)的直接非静态数据成员) 或无法复制/移动的直接基类 M 因为重载决议 (16.3) 应用于查找 M 的相应赋值运算符会导致歧义或从默认赋值运算符中删除或无法访问的函数。

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

    类 X 的默认析构函数在以下情况下被定义为已删除:
    — (5.1) X 是一个类联合类,它具有带有非平凡析构函数的变体成员,
    — (5.2) 任何潜在构造的子对象都具有类类型 M(或其数组)和 M 具有已删除的析构函数或无法从默认析构函数访问的析构函数,
    -(5.3)或者,对于虚拟析构函数,查找非数组释放函数会导致歧义或函数被删除或无法从默认的析构函数访问。

于 2017-09-25T10:55:49.710 回答