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 ...
随机推荐
- 【TP3.2】模板 select选项采坑
1.TP3.2 模板 select 下拉框采坑 <div class="form-item"> <label class="item-label&quo ...
- kubernetes-pod分配CPU和RAM资源以及计算方法
例子: Containers: cpu-ram-demo-container: ... image: busybox:latest resources: Limits: cpu: 1 memory: ...
- ios中地图定位
#import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> @interface ViewController ...
- NoSQL生态系统(nosql ecosystem)
Unlike most of the other projects in this book, NoSQL is not a tool, but an ecosystem composed of se ...
- Android轻量级ORM框架ActiveAndroid入门教程(转)
注:没有找到出处,如有侵犯,请告知 开始ActiveAndroid神奇之旅: 在AndroidManifest.xml中我们需要添加这两个 AA_DB_NAME (数据库名称,这个name不能改,但是 ...
- JAVA删除文件及文件夹
JAVA在删除文件或文件夹时,在java.io.File类下有个delete的方法,并且可以返回true or false, 用这个方法来删除单个文件时,很好使,但在删除文件夹时,如果文件夹下面有文件 ...
- 【HTML】网页中如何让DIV在网页滚动到特定位置时出现
用js或者jquery比较好实现.但你要知道,滚动到哪个特定位置,例如滚动到一个标题h3那显示这个div,那么可以用jquery算这个h3距离网页顶部的距离:$("h3").off ...
- 【struts2】预定义拦截器
1)预定义拦截器 Struts2有默认的拦截器配置,也就是说,虽然我们没有主动去配置任何关于拦截器的东西,但是Struts2会使用默认引用的拦截器.由于Struts2的默认拦截器声明和引用都在这个St ...
- 【colaboratory】在colab中安装mxnet
在学习<动手学深度学习>内容是,该内容用的是mxnet框架,在电脑本地安装过程中又容易出现错误,怎么也安装不上,所有的条件都尝试了. 汗颜,指的另谋他法. 只有在谷歌的学习平台上安装使用h ...
- Android View之布局加载流程
1.引言 最近准备重新学习下Android,加深理解,快速形成自己的知识结构体系.最先学习的就算View部分,从自定义View到Activty层次结构,到layout加载过程.等等都会看一遍,在此记录 ...