下面的代码中,为什么POD被认为是POD,而notPOD被认为不是POD呢?它们之间的唯一区别是默认构造函数的定义是放在类内部还是外部。我一直认为两者做同样的事情,但事实显然并非如此。
#include <iostream>
struct POD {
POD() = default;
};
struct notPOD {
notPOD();
};
notPOD::notPOD() = default;
int main() {
std::cout << std::boolalpha << std::is_pod<POD>() << ' ' << std::is_pod<notPOD>() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
use*_*522 14
首先,术语“POD 类型”已经过时,并且std::is_pod自 C++20 起已被弃用。该概念已分为多个更具体的概念,这些概念更适用于人们期望 POD 类型的特定行为。特别是新概念是普通类型和标准布局类型。
你的问题是这门课是否琐碎。如果一个类是平凡可复制的,并且至少有一个合格的默认构造函数,并且所有此类构造函数都是平凡的,那么该类就是平凡的。
仅当默认构造函数“不执行任何操作”并且不是用户提供的时,它才是微不足道的。在您的示例中,默认构造函数在这两种情况下都不执行任何操作,但在第一个示例中它不是用户提供的,而在第二个示例中是用户提供的。如果构造函数没有隐式声明(即用户实际编写了其声明),并且它在其第一个声明中(即在类内部)不是默认的,则该构造函数是用户提供的,这是两个示例之间的区别。
这条规则的原因是所有翻译单元必须就默认构造函数和类是否平凡达成一致。此类型特征附加了语言规则,这些规则在不同的翻译单元中不得有所不同。
如果构造函数在类内部默认,则所有翻译单元都必须同意这一点,因为具有类定义的翻译单元也必须在其声明中默认构造函数。不同翻译单元中类的定义必须是标记相同的,否则定义将违反单一定义规则,并且程序将无效。
如果您在类外部默认构造函数,则只有具有默认构造函数的一个翻译单元才能看到它。另一个翻译单元可能包括类定义,但不需要包括构造函数的默认定义,因此它可能不知道它是默认的。那么就不可能说构造函数是否是用户在每个翻译单元中提供的,特别是其他翻译单元可能不知道构造函数是否实际上“不执行任何操作”。所以它不能被认为是微不足道的。
换句话说,特征必须仅依赖于类定义,以便在翻译单元之间保持一致。它不能依赖于类定义之后的附加声明。因此,规则是这样的构造函数和类并不简单。