C++11 POD类型
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)这两个方面。
#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类型的更多相关文章
- c++11 pod类型(了解)
啥是POD类型? POD全称Plain Old Data.通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型. 平凡的定义 .有平凡的构造函数 .有平凡的拷贝构造函数 ...
- POD类型
POD类型 POD全称Plain Old Data.通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型. C++11将POD划分为两个基本概念的合集,即:平凡的和标准 ...
- 3. C++ POD类型
POD全称Plain Old Data,通常用于说明1个类型的属性.通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型. C++11将POD划分为2个基本概念的合集, ...
- 聚合类型与POD类型
Lippman在<深度探索C++对象模型>的前言中写道: I have heard a number of people over the years voice opinions sim ...
- C++ POD 类型
POD 是 C++ 中一个比较重要的概念,POD 是英文 Plain Old Data 的缩写(通俗讲就是类或结构体通过二进制拷贝后还能保持其数据不变),用来描述一个类型(包括 class.union ...
- C++ trivial和non-trivial构造函数及POD类型(转)
原博客地址http://blog.csdn.net/a627088424/article/details/48595525 最近正纠结这个问题就转过来了,做了点补充(参考<深度探索C++对象模型 ...
- 关于POD和非POD类型中,list initialization和constructor initialization(未解决)
如果你的成员是POD类型的,那么list initialization和constructor initialization没有任何区别 #include<iostream> using ...
- 关于C++ 中POD类型的解析
转自: http://liuqifly.spaces.live.com/blog/cns!216ae3a149106df9!221.entry (C++-98:1.8;5)给出的定义:将对象的各字节拷 ...
- C++ POD类型
POD( Plain Old Data)概念: Arithmetic types (3.9.1), enumeration types, pointer types, and pointer to m ...
随机推荐
- 转:OGRE 源码编译方法
编译及运行环境:Windows 7 . vs2010. 编译前的准备: 1.想编译OGRE,最起码要有OGRE的源码吧.可以去官方网站下载最新的源码包,我这里用的是1.7.2版本的,下载下来的文件叫 ...
- Android 控件进阶修炼-仿360手机卫士波浪球进度控件
技术:Android+java 概述 像360卫士的波浪球进度的效果,一般最常用的方法就是 画线的方式,先绘sin线或贝塞尔曲线,然后从左到右绘制竖线,然后再裁剪圆区域. 今天我这用图片bitma ...
- 解决inline-block上下不对齐
一开始都是行内元素,但是左边按钮和右边标题就是对不齐,于是,设置左边按钮float:left就可以了. <header class="right-header"> &l ...
- 存储过程—导出table数据为inser sqlt语句
Sql Server Management Studio没有将table中数据导出为insert语句的功能. 下面一个很有用的存储过程,可以把某张表的数据导出为insert sql语句.当然Oracl ...
- 架构-虚拟路由器冗余协议【原理篇】VRRP详解
转自:http://zhaoyuqiang.blog.51cto.com/6328846/1166840/ 为什么要使用VRRP技术 我们知道,为了实现不同子网之间的设备通信,需要配置路由.目前常用的 ...
- [转]图解分布式一致性协议Paxos
Paxos协议/算法是分布式系统中比较重要的协议,它有多重要呢? <分布式系统的事务处理>: Google Chubby的作者MikeBurrows说过这个世界上只有一种一致性算法,那就是 ...
- C语言学习笔记 (003) - C/C++中的实参和形参(转)
今天突然看到一道关于形参和实参的题,我居然不求甚解.藐视过去在我的脑海里只有一个参数的概念,对于形参和实参的区别还真的不知道,作为学习了几年C++的人来说,真的深深感觉对不起自己对不起C++老师 T ...
- Redis学习之路(002)- Ubuntu下redis开放端口
Redis在ubuntu安装后默认是只有本地访问,需要别的ip访问我们需要修改redis的配置文件 1. dpkg -L redis-server 这命令我们可以看到redis的安装的文件在那些目录 ...
- 深入学习 Git 工作流
原文 https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md 个人在学习git工作流的过程中,从原有的 SVN ...
- ROS学习(五)—— 编译ROS Package
提前准备: 记得事先source你的环境配置(setup)文件,在Ubuntu中的操作指令如下. source /opt/ros/kinetic/setup.bash 一.使用catkin_make ...