用外行的话来说,平凡类型,标准布局类型和POD有什么区别?
具体来说,我想确定是否new T
与new T()
任何模板参数不同T
。哪种类型的性状is_trivial
,is_standard_layout
而且is_pod
我应该选择?
(作为附带的问题,这些类型特征中的任何一种都可以在没有编译器魔术的情况下实现吗?)
用外行的话来说,平凡类型,标准布局类型和POD有什么区别?
具体来说,我想确定是否new T
与new T()
任何模板参数不同T
。哪种类型的性状is_trivial
,is_standard_layout
而且is_pod
我应该选择?
(作为附带的问题,这些类型特征中的任何一种都可以在没有编译器魔术的情况下实现吗?)
Answers:
我认为,至少在没有大量额外解释的情况下,这不是真正意义上的外行人可以做到的。重要的一点是静态初始化与动态初始化,但是向外行解释,其本身将是几页...
POD在(C ++)98中定义。确实有两个单独的意图,它们都没有很好地表达:1)如果您在C ++中编译C struct声明,则所获得的内容应等同于C中的内容。2)POD仅会需要/使用静态(非动态)初始化。
C ++ 0x / 11(几乎)完全放弃了“ POD”标记,而赞成“琐碎的”和“标准布局”。标准布局旨在捕获第一个意图-使用与C语言中相同的布局创建某些内容。Trivial旨在捕获对静态初始化的支持。
由于new T
vs.new T()
负责初始化,因此您可能需要is_trivial
。
我不确定是否需要编译器魔术。我的即时反应可能是肯定的,但是了解人们使用TMP所做的一些事情后,我很难确定某人也无法做到这一点...
编辑:例如,也许最好引用N3290的示例:
struct N { // neither trivial nor standard-layout
int i;
int j;
virtual ~N();
};
struct T { // trivial but not standard-layout
int i;
private:
int j;
};
struct SL { // standard-layout but not trivial
int i;
int j;
~SL();
};
struct POD { // both trivial and standard-layout
int i;
int j;
};
无疑,POD
这也是POD结构。
trivial + standard layout = POD
总是成立吗?
对于POD类型new T()
是value-initialization(将对所有成员进行value-initialization),并且new T
不会初始化成员(默认初始化)。有关不同形式的初始化之间的差异,请参见此问题。底线:您需要is_pod
。
布局是类,结构或联合的对象的成员在内存中的排列方式。这可能是不连续的。语言经常指定布局,但是如果存在诸如虚函数,虚拟基类等内容,那么编译器可以自由选择布局,而这可能不是连续的。这导致了一些问题,我们无法适当地序列化对象或将其传递给使用其他语言(如C)或函数(如memcopy)编写的程序,因为我们无法可靠地复制不在相邻位置的数据。
为了使编译器和c ++程序能够支持上述操作,c ++为简单的结构和类引入了3类。
不重要的
如果一个类或结构遵循以下规则,则它是微不足道的:
如果一个类是琐碎的,则其布局是连续的,但可能会有相应的填充,并且编译器可以自由选择布局中成员的顺序。因此,即使我们可以复制对象,如果将对象复制到C程序中也不可靠。我们可以在同一个类中拥有不同的访问说明符,并且如果使用参数化构造函数,则显然必须指定默认构造函数。但是,如果您想让该类变得微不足道,则应显式将构造函数设为默认值。构造函数应为public。
标准版式
标准布局定义明确,可以可靠地复制并适当地传递给C程序。同样,标准布局功能可以具有用户定义的特殊成员功能,例如构造函数和析构函数。
POD(普通旧数据)
如果一个类或结构既是普通布局又是标准布局,则称其为POD。每个成员均按声明对象时指定的顺序存储。POD类应具有POD非静态数据成员.POD类可以可靠地复制或传递给C程序。
C ++程序的类很小,是标准布局,因此是POD。
#include<iostream>
#include<type_traits>
class xyz
{
public:
int a;
int b;
xyz() = default;
xyz(int x, int y) :a(x), b(y) {}
};
int main() {
std::cout << std::is_trivial<xyz>() << std::endl;//true
std::cout << std::is_standard_layout<xyz>() << std::endl;//true
std::cout << std::is_pod<xyz>() << std::endl;//true
}
文字类型
对于文字类型,可以在编译时确定布局。文字类型的示例为void,标量类型(如int,float等),引用,void的数组,标量类型或引用以及具有琐碎析构函数的类,以及不是移动或复制构造函数的一个或多个constexpr构造函数。此外,其所有非静态数据成员和基类必须是文字类型,并且不是易变的