POD:Plain Old Data的缩写。是c++中一个非常重要的概念。
Plain,表示了POD是个普通类型。
Old,体现了其与c的兼容
c++11中将POD划分为两个基本概念的集合。
平凡 trivial
标准布局 standard layout
平凡
一个平凡的类或结构体应该符合以下定义。
1)拥有平凡的默认构造函数(trivial constructor)和析构函数(trivial destructor)
也就是说构造函数什么也不做。一般来说,不定义类的构造函数,编译器生成的构造函数就是平凡的构造函数。
一旦自己定义了构造函数,即使没有参数,代码体也没有任何代码,那么构造函数也不再是平凡的了。
例:
struct Notrivial{Notrivial(){};};
2)拥有平凡的拷贝构造函数和移动构造函数。(参考1))
3)拥有平凡的拷贝赋值函数和移动赋值函数。(参考1))
4)不能包含虚函数以及虚基类。
c++11中可以通过类模板帮助我们判断。
头文件 type_triats
templete <typename T> struct std::is_trivial;
例:
#include <iostream>
#include <type_traits>
class Trivial
{
};
class NoTrivial
{
NoTrivial() {}
};
int main()
{
std::cout << std::is_trivial<Trivial>::value << std::endl; //1
std::cout << std::is_trivial<NoTrivial>::value << std::endl; //0
system("pause");
return 0;
}
平凡的总结
平凡是我们定义的任何操作不会对类或者结构体的构造,拷贝,赋值,析构过程产生任何的影响。
标准布局
定义:
1)所有静态成员有相同的访问权限。
c++规定相同权限的非静态成员变量的类内的定义顺序是固定的,
与声明时的顺序相同,不同权限的非静态成员变量的顺序,没有设置要求。
所以要有相同的访问权限
2)在类后者结构体继承时,满足以下两种情况之一:
1:派生类中有非静态成员,且只有一个仅包含静态成员的基类。
2:基类有非静态成员,而派生类中没有非静态成员。
实际上非静态成员同时出现在基类和派生类中,派生类就不属于标准布局。
3)类中第一个非静态成员的类型与其基类不同。
c++标准要求类型相同的对象必须地址不同
(基类地址及派生类中第一个非静态成员地址必须不同)
为了区分类变量与类成员变量,
编译器会添加1字节空间。
c++中如果基类没有成员,标准允许派生类的第一个成员与基类共享地址。
4)没有虚函数和虚基类
虚函数和虚基类,一般的编译器会添加一个vtpr(virtual table pointer)变量。
5)所有非静态成员均符合标准布局类型,其基类也符合标准布局。
c++11中可以通过类模板帮助我们判断。
头文件 type_triats
templete <typename T> struct std::is_standard_layout;
例:
#include <iostream>
#include <type_traits>
class Slayout
{
};
class NoSlayout:public Slayout
{
Slayout a;
};
int main()
{
std::cout << std::is_standard_layout<Slayout>::value << std::endl; //1
std::cout << std::is_standard_layout<NoSlayout>::value << std::endl; //0
system("pause");
return 0;
}
标准布局的总结
POD判定
c++11中可以通过类模板帮助我们判断。
头文件 type_triats
templete <typename T> struct std::is_POD;
POD的好处:
1)字节赋值,代码中可以安全的使用memset和memecpy。
2)提供兼容C内存布局。
3)保证静态初始化的安全有效
掌握POD之后,对c++的内存布局就会有个大体的了解。
POD就是看起来什么样就是什么样。
例如:
struct S{
int a;
int b;
//函数定义
}
我们就知道这个结构体的对象模型(内存结构)是下面的这个样子的。
S x;
x 占 8字节
内部结构以及顺序是:
x.a 占 4字节 存着垃圾值
x.b 占 4字节 存着垃圾值顺序和字节数表示的是标准布局
垃圾值表示的是平凡
所以,看起来就是C的结构体。
推荐书籍《C++ Object Model》(c++对象模型)