提问



我曾经多次遇到这个术语POD型。
这是什么意思?

最佳参考


POD 代表普通旧数据 - 即没有构造函数,析构函数的类(无论是使用关键字struct还是关键字class定义的)和虚拟成员功能。维基百科关于POD的文章更详细,并将其定义为:[27]



  C ++中的普通旧数据结构是一个聚合类,它只包含PODS作为成员,没有用户定义的析构函数,没有用户定义的复制赋值运算符,也没有指向成员类型的非静态成员。



在C ++ 98/03的答案中可以找到更多细节。 C ++ 11改变了围绕POD的规则,使它们大大放松,因此需要在这里进行后续回答。

其它参考1


非常非正式地:



POD是一种类型(包括类),其中C ++编译器保证结构中不会出现魔法:例如,隐藏指向vtable的指针,在转换为其他类型时应用于地址的偏移量(至少如果目标是POD,构造函数或析构函数。粗略地说,当一个类型中的唯一内容是内置类型和它们的组合时,类型就是POD。结果是行为类似的东西C型。


不那么非正式:




  • intcharwchar_tboolfloatdouble是POD,long/short和[[signed/unsigned他们的版本。

  • 指针(包括指向函数的指针和指向成员的指针)是POD,

  • enums是POD

  • a constvolatile POD是POD。

  • POD的classstructunion是POD,前提是所有非静态数据成员都是public,它没有基类,也没有构造函数,析构函数或虚拟方法。根据这条规则,静态成员不会阻止某事成为POD。

  • 维基百科说POD不能包含指向成员的类型成员是错误的。或者更确切地说,它对于C ++ 98的措辞是正确的,但TC1明确表示指向成员的指针是POD。



形式上(C ++ 03标准):




   3.9(10):算术类型(3.9.1),枚举类型,指针类型和指向成员类型的指针(3.9.2)以及这些类型的cv限定版本(3.9.3)标量类型,POD结构类型,POD-union类型(第9节),这些类型的数组和这些类型的cv限定版本(3.9.3)统称为POD类型

  
   9(4):POD-struct是一个聚合类,没有非POD-struct类型的非静态数据成员,非POD-union(或此类型的数组)或引用,没有用户定义的复制操作符,也没有用户定义的析构函数。类似地,POD-union是一个聚合联合,它没有非POD-struct,非POD-union(或数组)类型的非静态数据成员这些类型)或引用,并没有用户定义的复制操作符和用户定义的析构函数。

  
   8.5.1(1):聚合是一个数组或类(第9节),没有用户声明的构造函数(12.1),没有私有或受保护的非静态数据成员(第11节),没有基类(第10节)和虚函数(10.3)。


其它参考2


普通旧数据[30]


简而言之,它是所有内置数据类型(例如intcharfloatlongunsigned chardouble等。)和POD数据的所有聚合。是的,这是一个递归的定义。;)


更清楚一点,POD就是我们所说的结构:一个单元或一组只存储数据的单元。

其它参考3


据我所知,POD(PlainOldData)只是一个原始数据 - 它不需要:



  • 待建,

  • 被摧毁,

  • 拥有自定义运营商。

  • 必须没有虚拟功能,

  • 并且不得覆盖运营商。



如何检查某些东西是否是POD?那么,有一个名为std::is_pod的结构:


namespace std {
// Could use is_standard_layout && is_trivial instead of the builtin.
template<typename _Tp>
  struct is_pod
  : public integral_constant<bool, __is_pod(_Tp)>
  { };
}


(来自header type_traits)



参考:



  • http://en.cppreference.com/w/cpp/types/is_pod

  • http://en.wikipedia.org/wiki/Plain_old_data_structure

  • http://en.wikipedia.org/wiki/Plain_Old_C++_Object

  • 文件type_traits


其它参考4


POD(普通旧数据)对象具有以下数据类型之一 - 基本类型,指针,联合,结构,数组或类 - 没有构造函数。相反,非POD对象是构造函数所在的对象。当POD对象获得具有适合其类型的大小的存储时,它的生命周期开始,并且当对象的存储被重用或解除分配时,它的生命周期结束。[31] [32] [33]


PlainOldData类型也不能包含以下任何内容:



  • 虚拟功能(自己的或继承的)

  • 虚拟基类(直接或间接)。



PlainOldData的更宽松定义包括具有构造函数的对象;但不包括虚拟的东西。 PlainOldData类型的重要问题是它们是非多态的。可以使用POD类型进行继承,但是它应该仅针对ImplementationInheritance(代码重用)而不是多态/子类型进行。


一个常见的(虽然不是严格正确的)定义是PlainOldData类型是没有VeeTable的任何东西。

其它参考5


POD的概念和类型特征std::is_pod将在C ++ 20中弃用。有关详细信息,请参阅此问题。

其它参考6


使用C ++,Plain Old Data并不仅仅意味着像int,char等这样的东西是唯一使用的类型。普通旧数据实际上意味着你可以将一个struct memcpy从内存中的一个位置转移到另一个位置。完全像你期望的那样工作(即没有爆炸)。如果你的类或你的类所包含的任何类作为一个指针或引用的成员或具有虚函数的类,这会中断。基本上,如果指针必须涉及某个地方,它不是普通的旧数据。