用外行人的话来说,琐碎的类型,标准版面类型和POD之间有什么区别?
具体来说,我想确定new T
对于任何模板参数new T()
是否与T
不同。我应该选择哪种类型特征is_trivial
,is_standard_layout
和is_pod
?
(作为一个附带问题,可以在没有编译魔术的情况下实现这些类型特征中的任何一个吗?)
答案 0 :(得分:54)
我不认为这可以用真正的外行人的术语来完成,至少没有很多的额外解释。一个重要的点是静态与动态初始化,但向外行解释这本身就是几页......
在C ++ 98中定义了(错误)POD。实际上有两个单独的意图,都没有表达得很好:1)如果你在C ++中编译一个C结构声明,你得到的应该与你在C中的相同.2)POD只需要/使用静态(不是动态的)初始化。
C ++ 0x / 11完全删除了“POD”(几乎)的名称,支持“琐碎”和“标准布局”。标准布局旨在捕获第一个意图 - 使用与C中相同的布局创建内容.Trivial旨在捕获对静态初始化的支持。
由于new T
与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结构。
答案 1 :(得分:7)
对于POD类型new T()
是值初始化(将对所有成员进行值初始化),new T
不会初始化成员(默认初始化)。对于不同形式的初始化see this question之间的差异。底线:您需要is_pod
。
答案 2 :(得分:0)
布局 是类,结构或联合的对象的成员在内存中的排列方式。这可能是不连续的。语言经常指定布局,但是如果存在诸如虚函数,虚拟基类等内容,那么编译器可以自由选择布局,而这可能不是连续的。这导致了一些问题,我们无法适当地序列化对象或将其传递给使用其他语言(如C)或函数(如memcopy)编写的程序,因为我们无法可靠地复制不在相邻位置的数据。
为了使编译器和c ++程序能够支持上述操作,c ++为简单的结构和类引入了3类。
优惠
如果类或结构遵循以下规则,则它是微不足道的:
如果一个类是琐碎的,则其布局是连续的,但可能会有相应的填充,并且编译器可以自由选择布局中成员的顺序。因此,即使我们可以复制对象,如果将对象复制到C程序中也不可靠。我们可以在同一个类中拥有不同的访问说明符,并且如果使用参数化构造函数,则显然必须指定默认构造函数。但是,如果您想让该类琐碎,那么应该显式地将构造函数设为默认值。构造函数应该是公共的。
标准版式
标准布局定义明确,可以可靠地复制并适当地传递给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构造函数 构造函数。此外,其所有非静态数据成员和基类都必须是文字类型,并且必须是可变的