POD数据类型

看《STL源码剖析》时发现了POD类型这个名词,一开始初步的理解就是普通数据类型,后来查了查比较完整的定义。

POD是Plain Old Data的缩写,是 C++ 定义的一类数据结构概念,比如 int、float 等都是 POD 类型的。两个系统进行交换数据,如果没有办法对数据进行语义检查和解释,那就只能以非常底层的数据形式进行交互,而拥有 POD 特征的类或者结构体通过二进制拷贝后依然能保持数据结构不变。也就是说,能用C语言的memcpy(),memset()等函数进行操作的类、结构体就是POD类型的数据。一般我们要研究的问题是某class, struct, union是不是POD,在STL中就是元素的类型了。

POD的特点

POD类型要满足两个特征:trivial和布局有序。我们可以用std::is_trivial<T>::value判断一个类型是否是POD

对于class,struct,要成为POD类型说白了就是要 “像” C语言下的struct,因此要满足下面条件:

  1. 不能自定义构造/析构函数、拷贝/移动构造函数、拷贝/移动运算符,而是用编译器自动为我们生成的默认版本,那这个数据就是trivial。非要写的话,用 C++ 11 的 default 关键字。

  2. 不能有虚函数和虚基类,否则肯定会具备面向对象特性了

  3. 非静态成员变量的访问级别相同

  4. 派生类不增加新的成员变量,因为 C 没有继承的概念,所以不要把普通成员在两个类中都写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A
{
};
class B
{
B(){}
};
class C
{
C()=default;
};

qDebug()<<std::is_trivial<A>::value; //true
qDebug()<<std::is_trivial<B>::value; //false,自定义构造函数
qDebug()<<std::is_trivial<C>::value; //true,使用默认构造函数

来试验一下memcpy操作POD类型:

1
2
3
4
5
6
7
8
    C obj;
obj.a = 13;
obj.b = 99;
// memset(&obj, 0 ,sizeof(obj));
int *foo = new int(sizeof(C));
memcpy(foo,&obj,sizeof(C));
C* t = reinterpret_cast<C*>(foo);
qDebug()<<t->a<<" "<<t->b;

运行结果是13 99