class 删除的析构函数被认为是可简单复制的?
class with deleted destructor considered trivially copyable?
这可以用 gcc 和 clang 编译
#include <type_traits>
struct A {
~A() = delete;
};
static_assert(std::is_trivially_copyable_v<A>);
int main() { }
删除了析构函数的class是否可以简单复制?
我假设A的析构函数被隐式删除,= delete;
没有影响,不计入std::is_trivially_copyable_v<A>
。
扩展示例也是如此
#include <type_traits>
struct A {
int a;
int b;
~A() = delete;
};
static_assert(std::is_trivially_copyable_v<A>);
int main() { }
The implicitly-declared or defaulted destructor for class T is defined as deleted (since C++11) if any of the following is true:
- has a non-static data member that cannot be destructed (has deleted or inaccessible destructor)
...
= delete
不会改变析构函数的属性“已删除隐式声明的析构函数”,因此上面的 class A 与下面的 class A 相同:
struct A {
int a;
int b;
};
条件“有一个普通的未删除的析构函数”为真。
我只有一个想法。由于隐式析构函数已经不可用,因此 具有一个普通的未删除析构函数 的要求不会被不可用析构函数的 = delete
违反,无需删除。但是 = delete
使用户声明的隐式删除析构函数(使其可用)。让我们看看 int main() { A a; }
编译器不会像您的 A
示例那样调用不可用的析构函数,而是必须像我的 A
示例那样调用用户声明的析构函数,并且它被删除(被可用)。
可简单复制的 class 可能没有已删除的构造函数
考虑到该主题的标题和未来的读者:标准完全清楚 A
定义为
struct A {
~A() = delete;
};
根据 [class.prop]/1, 不是简单可复制的 class,特别是 /1.3
A trivially copyable class is a class:
- (1.1) that has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator
([special], [class.copy.ctor], [class.copy.assign]),
- (1.2) where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and
- (1.3) that has a trivial, non-deleted destructor ([class.dtor]).
至于为什么 GCC 和 Clang 都不遵守这一点,在 Clang 错误报告中
理查德史密斯评论
(R. Smith) This is
DR1734,
which Clang (and apparently GCC) does not yet implement.
之后讨论了为什么这很难实现(ABI 兼容性问题),但没有提及实际尝试提交 DR 或类似文件以更改或挑战标准文本;例如:
(R. Smith) [...] The part of the ABI I was referring to is "POD for the purpose of layout", for which various different targets use different rules, and the four that I listed above base their rule on Clang's broken notion of "trivially-copyable".
因此,从语言律师的角度来看,该主题的标准非常明确:A
不可 简单复制。
这可以用 gcc 和 clang 编译
#include <type_traits>
struct A {
~A() = delete;
};
static_assert(std::is_trivially_copyable_v<A>);
int main() { }
删除了析构函数的class是否可以简单复制?
我假设A的析构函数被隐式删除,= delete;
没有影响,不计入std::is_trivially_copyable_v<A>
。
扩展示例也是如此
#include <type_traits>
struct A {
int a;
int b;
~A() = delete;
};
static_assert(std::is_trivially_copyable_v<A>);
int main() { }
The implicitly-declared or defaulted destructor for class T is defined as deleted (since C++11) if any of the following is true:
- has a non-static data member that cannot be destructed (has deleted or inaccessible destructor)
...
= delete
不会改变析构函数的属性“已删除隐式声明的析构函数”,因此上面的 class A 与下面的 class A 相同:
struct A {
int a;
int b;
};
条件“有一个普通的未删除的析构函数”为真。
我只有一个想法。由于隐式析构函数已经不可用,因此 具有一个普通的未删除析构函数 的要求不会被不可用析构函数的 = delete
违反,无需删除。但是 = delete
使用户声明的隐式删除析构函数(使其可用)。让我们看看 int main() { A a; }
编译器不会像您的 A
示例那样调用不可用的析构函数,而是必须像我的 A
示例那样调用用户声明的析构函数,并且它被删除(被可用)。
可简单复制的 class 可能没有已删除的构造函数
考虑到该主题的标题和未来的读者:标准完全清楚 A
定义为
根据 [class.prop]/1,struct A { ~A() = delete; };
不是简单可复制的 class,特别是 /1.3
A trivially copyable class is a class:
- (1.1) that has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator ([special], [class.copy.ctor], [class.copy.assign]),
- (1.2) where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and
- (1.3) that has a trivial, non-deleted destructor ([class.dtor]).
至于为什么 GCC 和 Clang 都不遵守这一点,在 Clang 错误报告中
理查德史密斯评论
(R. Smith) This is DR1734, which Clang (and apparently GCC) does not yet implement.
之后讨论了为什么这很难实现(ABI 兼容性问题),但没有提及实际尝试提交 DR 或类似文件以更改或挑战标准文本;例如:
(R. Smith) [...] The part of the ABI I was referring to is "POD for the purpose of layout", for which various different targets use different rules, and the four that I listed above base their rule on Clang's broken notion of "trivially-copyable".
因此,从语言律师的角度来看,该主题的标准非常明确:A
不可 简单复制。