理解POD数据类型
1.什么是POD?
POD全称Plain Old Data。字面意思,普通的,旧的数据类型。通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型。
2.C++11中的定义
在*中有:
C ++中的普通旧数据结构是一个聚合类,它只包含PDS作为成员,没有用户定义的析构函数,没有用户定义的复制赋值运算符,也没有指向成员类型的非静态成员。被动数据结构(PDS( passive data structure ),不要与IBM的分区数据集混淆;也称为普通旧数据结构,或普通旧数据(POD)),是一个记录术语,与物体形成对比。它是一种数据结构,仅表示为字段值(实例变量)的被动集合,而不使用面向对象的功能。
在C++11中POD包含两个类型trivial(平凡的,普通的) 和 standard-layout(标准布局) 。
什么是trivial(平凡的)?
trivial类型支持静态初始化。如果一个类型是拷贝不变的(trivially copyable),使用memcpy这种方式把它的数据从一个地方拷贝出来会得到相同的结果。
C++标准把trivial(平凡的)类型定义如下:
-
平凡的复制构造函数
-
平凡的转移构造函数
- 平凡的赋值操作符
-
平凡的转移赋值操作符
- 平凡的析构函数
- 没有虚函数和虚基类
#include <iostream>
#include<type_traits>
using namespace std;
//空类是平凡的
//以下是平凡的
class Trival1 {};
struct Trival1_1{int x;double y;};
class Trival1_2{
public:
int x;
private:
int y;
};
///////以下是no-trival,不是POD类型
//非平凡的构造函数
class Trival2 { Trival2(){} };
//非平凡的拷贝构造函数
class Trival3 { Trival3(Trival3&){} };
//非平凡的拷贝赋值运算符
class Trival4 { Trival4 operator=(Trival4&){} };
//非平凡的移动赋值运算符
class Trival5 { Trival5 operator=(Trival5&&){} };
//非平凡的析构函数
class Trival6 { ~Trival6(){} };
//有虚函数---不是trival,不是POD
class Trival7 { virtual void foo() = 0; };
//有虚基类 --- 不是trival,不是POD
class Trival8 : Trival7 {};
int main()
{
//基本数据类型是平凡的(trival),也就是POD的
cout << std::is_trivial<int>::value << endl;
cout << std::is_trivial<Trival1>::value << endl;
cout << std::is_trivial<Trival1_1>::value << endl;
cout << std::is_trivial<Trival1_2>::value << endl;
cout << std::is_trivial<Trival2>::value << endl;
cout << std::is_trivial<Trival3>::value << endl;
cout << std::is_trivial<Trival4>::value << endl;
cout << std::is_trivial<Trival5>::value << endl;
cout << std::is_trivial<Trival6>::value << endl;
cout << std::is_trivial<Trival7>::value << endl;
cout << std::is_trivial<Trival8>::value << endl;
return 0;
}
什么是standard-layout(标准布局)?
C++标准中的是这样定义的:
- 所有的非静态数据成员都符合标准布局或是引用的
-
没有虚函数和虚基类
- 非静态数据成员的访问控制必须是相同的
- 基类都符合标准布局
-
在派生类中没有非静态数据成员,且在基类中最多有一个基类拥有非静态数据成员,也就是说在整个的继承关系中,最多有1个基类有非静态数据成员(含0个)并且子类不能有非静态数据成员
- 相同基类类型的非静态数据成员不能作为第一个成员,也就是说在子类中的第一个非静态数据成员不能是父类
standard-layout类型的struct就是以struct或class为关键字定义的standard-layout 类型。
standard-layout类型的union就是以union为关键字定义的standard-layout 类型。
#include <iostream>
#include<type_traits> //C++11中
//成员a和b具有不同的访问权限,不符合标准布局
class A
{
private:
int a;
public:
int b;
};
class B1
{
static int x1;
};
class B2
{
int x2;
};
//子类含有非静态数据成员,
//基类有1个非静态数据成员,不符合标准布局
class B_1 : B1, B2
{
int x;
};
//子类含有静态数据成员,
//基类有1个非静态数据成员,符合标准布局
class B_2 : B1,B2
{
static int x;
};
//第一个非静态成员是基类类型,不符合标准布局
class C1 {};
class C_1 : C1
{
C1 c;
};
//第一个是静态数据成员的基类类型,符合标准布局
class C_2 : C1
{
static int C1;
int x;
};
//有虚函数,不符合标准布局
class D { virtual void foo() = 0; };
//有虚基类
class E : D {};
//非静态成员x不符合标准布局类型
class F { A x; };
int main()
{
//基本数据类型符合标准布局
std::cout << std::is_standard_layout<int>::value << std::endl;
std::cout << std::is_standard_layout<A>::value << std::endl;
std::cout << std::is_standard_layout<B_1>::value << std::endl;
std::cout << std::is_standard_layout<B_2>::value << std::endl;
std::cout << std::is_standard_layout<C_1>::value << std::endl;
std::cout << std::is_standard_layout<C_2>::value << std::endl;
std::cout << std::is_standard_layout<D>::value << std::endl;
std::cout << std::is_standard_layout<E>::value << std::endl;
std::cout << std::is_standard_layout<F>::value << std::endl;
return 0;
}
如何判断POD类型?
当一个数据类型满足了trival(平凡)和 standard_layout(标准布局),我们则认为它是一个POD数据。可以通过std::is_pod来判断一个类型是否为POD类型。
#include <iostream>
#include <type_traits>
struct A { int i; }; // C类型的结构体 ,是POD
class B : public A {}; // 是POD,没有数据成员
struct C : B { void fn(){} }; // 是POD,有成员函数
struct D : C { D(){} }; // 不是POD ,有默认的构造函数
int main()
{
std::cout << "int: " << std::is_pod<int>::value << std::endl;
std::cout << "A: " << std::is_pod<A>::value << std::endl;
std::cout << "B: " << std::is_pod<B>::value << std::endl;
std::cout << "C: " << std::is_pod<C>::value << std::endl;
std::cout << "D: " << std::is_pod<D>::value << std::endl;
return 0;
}
参考博客:
https://www.cnblogs.com/tingshuo/archive/2013/03/28/2986236.html
上一篇: 企业项目实战k8s篇(四)k8s控制器
下一篇: docker容器(2)——容器操作