POD通常用于说明一个类型的属性,尤其是用户自定义类型POD是一种普通属性,不像虚函数或虚继承那样特别,主要体现在与C兼容,可使用C的老方法,如memcpy等
POD被分为平凡的和标准布局的,两种基本概念
何为平凡的?
- 拥有平凡的默认构造函数和析构函数
- 如果定义了构造函数,这个类就失去了平凡的属性,但可以通用"=default"来显式声明其为缺省构造
- 拥有平凡的拷贝构造和移动构造函数
- 平凡拷贝构造函数基本等同于使用memcpy进行拷贝构造,也可使用"=default"
- 平凡移动构造与平凡拷贝构造类型,只是使用的是移动语义
- 拥有平凡的拷贝赋值运算符(trivial assignment operator)和移动赋值运算符(trivial move operator)
- 不能包含虚函数或虚基类
- 同时符合以上四点即为平凡的,但C++11中可以使用辅助方法std::is_trivial来进行判断
template <typename T> struct std::is_trivial;
**何为标准布局的?**标准布局应符合以下规则
- 所有非静态成员应该拥有相同的访问权限
- 类或结构体继承时,满足以下两种情况之一:
- 派生类中有非静态成员,且只有一个仅包含静态成员的基类
- 基类有非静态成员,而派生类没有非静态成员
- 类中第一个非静态成员的类型与其基类不同
PS:若基类中没有成员,派生类的第一个成员与基类共享地址
例如:
// A不是一个标准布局,这种情况下编译器会为基类分配1字节的空间导致的
struct A : B{ B b; };
//A是一个标准布局
struct C : B {int a; B b;};
-
没有虚函数和虚基类
-
所有非静态数据成员均符合标准布局类型,其基类也符合标准布局
-
同样地,C++11也提供辅助方法判断一个类型是否是标准布局的:
template <typename T> struct std::is_standard_layout;
但C++11比较智能,要判断一个类型是否是POD,不需要分别调用判断是否平凡、是否标准布局两种方法,它提供了一步就可以得到结果的方法:
template <typename T> struct std::is_pod;
POD有什么好处?
- 字节赋值,代码中我们可以安全地使用memset和memcpy对POD类型进行初始化和拷贝等操作
- 提供对C内存布局兼容。C++程序可以与C函数进行相互操作,因为POD类型的数据在C与C++间的操作总是安全的
- 保证了静态初始化的安全有效。静态初始化在很多时候能够提高程序的性能,而POD类型的对象初始化往往更加简单(比如放入目标文件的.bss段,在初始化中直接被赋0