POD,全称plain old data,plain代表它是一个普通类型,old代表它可以与c兼容,可以使用比如memcpy()这类c中最原始函数进行操作。C++11中把POD分为了两个基本概念的集合,即:平凡的(trival)和标准布局的(standard layout)。

1、首先是平凡的(trival)定义,通常一个平凡的类或者结构体需要满足以下定义

  (1).拥有平凡的默认构造函数和析构函数。默认的意思就是由编译器为我们自动生成的,不许是我们自己定义的,而一旦定义了构造函数,即使函数体里没有任何代码,那么该构造函数也不在是平凡的,但是由于c++11提供了default,也可以是自己定义的加=default。

  (2).拥有平凡的拷贝构造函数和移动构造函数。默认的意思同上,也可以使用=default。

  (3).拥有平凡的拷贝赋值运算符和移动赋值运算符。

  (4).不能包含虚函数和虚基类。

C++11中,我们使用模版类std::is_trivial<T>::value来判断数据类型是否为平凡类型。

#include "stdafx.h"
#include <iostream> using namespace std; class A { A(){} };
class B { B(B&){} };
class C { C(C&&){} };
class D { D operator=(D&){} };
class E { E operator=(E&&){} };
class F { ~F(){} };
class G { virtual void foo() = ; };
class H : G {};
class I {}; int _tmain(int argc, _TCHAR* argv[])
{
std::cout << std::is_trivial<A>::value << std::endl; //有不平凡的构造函数
std::cout << std::is_trivial<B>::value << std::endl; //有不平凡的拷贝构造函数
std::cout << std::is_trivial<C>::value << std::endl; //有不平凡的拷贝赋值运算符
std::cout << std::is_trivial<D>::value << std::endl; //有不平凡的拷贝赋值运算符
std::cout << std::is_trivial<E>::value << std::endl; //有不平凡的移动赋值运算符
std::cout << std::is_trivial<F>::value << std::endl; //有不平凡的析构函数
std::cout << std::is_trivial<G>::value << std::endl; //有虚函数
std::cout << std::is_trivial<H>::value << std::endl; //有虚基类
std::cout << std::is_trivial<I>::value << std::endl; //平凡的类return ;
}

2.接下来是标准布局的定义

(1).所有非静态成员拥有相同的访问级别,(访问级别就是public,private,protected)

struct t1{
private :
  int a;
public:
  int b;
}; //不满足标准布局,因为a,b访问级别不同。

(2).在类和结构体继承时需要满足以下两个情况之一:

  派生类中有非静态类,那么这个派生类只能有且只有一个仅包含了静态成员的基类。

  基类有非静态成员,那么派生类中不允许有非静态成员。

(这两句话看着挺绕口,其实就是在说明一个事实,关于非静态数据的事实,派生类中有非静态的数据那么它的基类只能是只有静态的,而且基类只能有一个。如果基类有非静态的, 那么派生类就不能有非静态的。有种跷跷板的感觉,非静态的对面坐着的是静态,父子类就 是坐在跷跷板的两端这种对应关系。)

(3).类中第一个非静态类型与基类不是同一个类型。比如

struct A:B{
B b;
int c;
} //不符合这个条件。因为A中第一个成员是基类B类型的

(4).没有虚类和虚基类(与trival中重复)

(5).所有非静态数据成员都符合标准布局的要求,这其实就是一个递归的定义。

C++11中,我们使用模版类std::is_standard_layout<A>::value来判断类型是否是一个标准布局类型。

所以在C++11中,POD就是满足平凡的(trival)和标准布局(standard layout)这两个方面。

可以使用<type_traits>中的is_pod<T>::value判断T是不是POD类型的。
#include <iostream>

using namespace std;

class A {
private:
int a;
public:
int b;
}; class B1 {
static int x1;
}; class B2 {
int x2;
}; class B : B1, B2 {
int x;
}; class C1 {};
class C : C1 {
C1 c;
}; class D { virtual void foo() = ; };
class E : D {};
class F { A x; }; int main()
{
std::cout << std::is_standard_layout<A>::value << std::endl; //违反定义1,成员a和b具有不同的访问权限
std::cout << std::is_standard_layout<B>::value << std::endl; //违反定义2,继承树有两个(含)以上的类有非静态成员
std::cout << std::is_standard_layout<C>::value << std::endl; //违反定义3,第一个非静态成员是基类类型
std::cout << std::is_standard_layout<D>::value << std::endl; //违反定义4,有虚函数
std::cout << std::is_standard_layout<E>::value << std::endl; //违反定义5,有虚基类
std::cout << std::is_standard_layout<F>::value << std::endl; //违反定义6,非静态成员x不符合标准布局类型
return ;
}
#include <iostream>
#include <cstring> using namespace std; class AA
{
public:
int x;
double y;
}; int main()
{
if (std::is_pod<AA>::value) {
cout << "before" << endl;
AA aa;
aa.x = ;
aa.y = 20.0f;
cout << aa.x << " " << aa.y << endl; size_t size = sizeof(aa);
char *p = new char[size];
memcpy(p, &aa, size); AA *pA = (AA*)p;
cout << "after" << endl;
cout << pA->x << " " << pA->y << endl;
delete p;
}
return ;
}

说了这么多,那么为什么我们需要POD这种条件满足的数据呢?

  (1).可以使用字节赋值,比如memset,memcpy操作

  (2).对C内存布局兼容。

  (3).保证了静态初始化的安全有效。

C++11 POD类型的更多相关文章

  1. c++11 pod类型(了解)

    啥是POD类型? POD全称Plain Old Data.通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型. 平凡的定义 .有平凡的构造函数 .有平凡的拷贝构造函数 ...

  2. POD类型

    POD类型 POD全称Plain Old Data.通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型. C++11将POD划分为两个基本概念的合集,即:平凡的和标准 ...

  3. 3. C++ POD类型

    POD全称Plain Old Data,通常用于说明1个类型的属性.通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型. C++11将POD划分为2个基本概念的合集, ...

  4. 聚合类型与POD类型

    Lippman在<深度探索C++对象模型>的前言中写道: I have heard a number of people over the years voice opinions sim ...

  5. C++ POD 类型

    POD 是 C++ 中一个比较重要的概念,POD 是英文 Plain Old Data 的缩写(通俗讲就是类或结构体通过二进制拷贝后还能保持其数据不变),用来描述一个类型(包括 class.union ...

  6. C++ trivial和non-trivial构造函数及POD类型(转)

    原博客地址http://blog.csdn.net/a627088424/article/details/48595525 最近正纠结这个问题就转过来了,做了点补充(参考<深度探索C++对象模型 ...

  7. 关于POD和非POD类型中,list initialization和constructor initialization(未解决)

    如果你的成员是POD类型的,那么list initialization和constructor initialization没有任何区别 #include<iostream> using ...

  8. 关于C++ 中POD类型的解析

    转自: http://liuqifly.spaces.live.com/blog/cns!216ae3a149106df9!221.entry (C++-98:1.8;5)给出的定义:将对象的各字节拷 ...

  9. C++ POD类型

    POD( Plain Old Data)概念: Arithmetic types (3.9.1), enumeration types, pointer types, and pointer to m ...

随机推荐

  1. FTP下载工具

    开源的FTP下载工具,FTP搬运工.... 01.FileZilla_3.21.0_win64 官方地址: https://filezilla-project.org/ 下载地址: http://pa ...

  2. sshd服务分析

    00.阐述 sshd 服务 基本上,所有的 ssh 相关设定都放在 /etc/ssh/sshd_config 里面!不过,每个 Linux distribution 的预设设定都不太相同, 所以我们有 ...

  3. Spring Boot 在IDEA中debug时的hot deployment(热部署)

    因为Spring Boot的项目一般会打包成jar发布, 在开发阶段debug时, 不能像传统的web项目那样, 选择exploded resources进行debug, 也没有热更新按钮, 如果每次 ...

  4. 基于SpringSecurity和JWT的用户访问认证和授权

    发布时间:2018-12-03   技术:springsecurity+jwt+java+jpa+mysql+mysql workBench   概述 基于SpringSecurity和JWT的用户访 ...

  5. usr/bin/X11各个程序中文详解

    X11程序 animate 输出图形结果 bitmap bmtoa bounce 输出X屏幕保存结果 display 浏览编辑image magick图像 editres 编辑X11资源 flsfon ...

  6. MATLAB 向量

    MATLAB 向量: 1.MATLAB 行向量: 创建行向量括在方括号中的元素的集合,用空格或逗号分隔的元素. 2.MATLAB 列向量: 创建列向量括在方括号中的元素的集合,使用分号来分隔的元素. ...

  7. Sentinel 简介与API订阅发布

    Sentinel 简介 Redis 的 Sentinel 系统用于管理多个 redis 服务器(instance), 该系统执行以下三个任务: 监控(Monitoring): Sentinel 会不断 ...

  8. 微信app支付

    http://www.bubuko.com/infodetail-1062014.html 要完成手机APP跳转到微信的APP进行微信支付,需要进行如下操作: 1.先去微信的开放平台(http://o ...

  9. hashCode和identityHashCode底层是怎么生成的

          前言:在工作中使用==埋下的坑这篇博文的最后,我想到了两个问题,其中一个是——为什么 int int1=99;int int2=99;int1和int2的identityHashCode是 ...

  10. 初步了解pandas(学习笔记)

    1 pandas简介 pandas 是一种列存数据分析 API.它是用于处理和分析输入数据的强大工具,很多机器学习框架都支持将 pandas 数据结构作为输入. 虽然全方位介绍 pandas API ...