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 ...
随机推荐
- According to TLD or attribute directive in tag file, attribute items does not accep t any expressions
According to TLD or attribute directive in tag file, attribute items does not accep t any expression ...
- VMware Workstation 10.0 简中绿色精简版
VMware Workstation是强大的虚拟机软件,能在一台机器上同时运行二个或更多Windows.DOS.LINUX系统,并进行开发.测试.部署新的应用程序.VMware10.0 延续VMwar ...
- Ubuntu系统下添加程序启动器
Ubuntu系统上安装的软件,有的会自动创建快捷方式,在程序中可以搜索到,而有的安装后不会在应用程序中出现,如Eclipse.Spring Tool Suite或是绿色软件等,那么怎么手动创建快捷方式 ...
- 【C++】不要依赖编译器的默认初始值
最好在定义的时候就给出初始值. 类和结构体给出构造函数. 比如int,在vs的debug和release模式下,初始化的值是不同的.
- java string截取两个字符串之间的值
java string截取两个字符串之间的值 import java.util.regex.Matcher; import java.util.regex.Pattern; public class ...
- kubernetes架构之二
一.概述 IaaS:即基础设施即服务,通过虚拟化和分布式存储等技术,实现对包括服务器.存储设备.网络设备等各种物理资源的抽象:从而形成了一个可扩展.可按需分配的虚拟资源池.最具代表性的IaaS产品有A ...
- Flume与Logstash比较
Flume与Logstash相比,个人的体会如下: Logstash比较偏重于字段的预处理:而Flume偏重数据的传输: Logstash有几十个插件,配置灵活:FLume则是强调用户的自定义开发(s ...
- 子类化GetOpenFileName/GetSaveFileName, 以及钩子函数OFNHookProc的使用的简要说明
昨天, 群里面有一个人问起: 要怎么让"文件打开对话框"居中显示, 有人说子类. 而我告诉他的方法是用钩子函数OFNHookProc, 不知道这是不是所谓的子类?相信看了我今天这篇 ...
- Python ---chart
# -*- coding:utf-8 -*- import random import matplotlib.pyplot as plt from pylab import * import os i ...
- linux文件系统 - 初始化(一)
术语表: struct task:进程 struct mnt_namespace:命名空间 struct mount:挂载点 struct vfsmount:挂载项 struct file:文件 st ...