理解POD数据类型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Qiana_/article/details/82078183

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

https://blog.csdn.net/aqtata/article/details/35618709

猜你喜欢

转载自blog.csdn.net/Qiana_/article/details/82078183
今日推荐