trivial、standard layout、POD和literal类型解析
参考资料
microsoft_trivial-standard-layout-and-pod-types
stackoverflow_trivial-vs-standard-layout-vs-pod
When is a type in c++11 allowed to be memcpyed?
is_pod vs is_trivial vs is_trivially_copyable vs is_standard_layout
关于layout
单词layout用于表示class、struct或union对象在内存中的分布,有些对象是连续占用内存区间的,而对于下面几种情况下对应的类对象,the compiler is free to choose a layout:
- 拥有虚基类的类
- 有虚函数的类
- 有不同访问权限数据成员的类(members with different access control)
这些类对象里面的内存可能不是连续分配的,所以不能使用memcpy
、memmove
类似的函数,也不可以serialized over a network
自C++11起,推出了三种traits,可以用来访问structs和classes的相关属性,分别是:
is_trivial<T>
is_standard_layout<T>
is_pod<T>
(C++20开始废弃)is_literal<T>
(C++17废弃,C++20移除)
下面分别介绍这四种类型的区别:
Trivial Type
When a class or struct in C++ has compiler-provided or explicitly defaulted special member functions, then it is a trivial type. Trivial types have a trivial default constructor, trivial copy constructor, trivial copy assignment operator and trivial destructor.
一个类,如果它的默认构造函数、拷贝构造函数、拷贝运算符重载和析构函数都是trivial函数,那它就是Trivial类。
那么如何判断一个函数是否为trivial函数呢,trivial函数需要满足以下几点:
- 函数是编译器自动生成的
- 只可以是六种类型的函数:default ctor、copy ctor、dtor、copy assignment operator、move ctor和move assignment operator
- 函数所在的类里没有虚函数或虚基类
- 如果函数所在类继承于一个基类,该基类相关的函数也必须是trivial函数
- 函数所在的类的类成员,也需要是trivial类
总结来说,如果一个类的上述四个函数都是编译器自动生成的,而且该类对应的基类和所有的成员都是trivial类型,且没有虚函数,则该类为trivial type。
参考代码如下:
#include<type_traits>
struct Trivial
{int i;
private:int j;// 注意,i和j的access不同,所以类Trivial是Trivial类,但不是standard layout类
};struct Trivial2
{int i;Trivial2(int a, int b) : i(a), j(b) {}Trivial2() = default;
private:int j; // Different access control
};struct NotTrivial
{int a;NotTrivial() :a(0) {};// 自定义ctor会让编译器不再生成default ctor
};struct NotTrivial2
{int a;virtual void Func() {}
};
int main()
{cout << std::is_trivial<Trivial>() << endl; // print 1cout << std::is_trivial<Trivial2>() << endl; // print 1cout << std::is_trivial<NotTrivial>() << endl; // print 0cout << std::is_trivial<NotTrivial2>() << endl; // print 0
}
trivial函数
trivial函数会影响以下方面(出自C++ Concurrency In Action(Second Edition) P361):
- 对于principle of three里的三个函数: 只有copy ctor、copy assignment operator和dtor都为trivial函数的类对应的对象,才可以用
memcpy
或memmove
来进行对象的复制 - 用于constexpr函数的Literal Types,需要有trivial copy ctor、trivial copy assignment operator和trivial dtor函数
- 如果一个类,其default ctor、copy assignment operator、copy ctor和dtor都为trivial函数,则该class can be used in a union with a user-defined ctor and dtor
- 如果一个类,定义了trivial copy assignment operator,则该类可以用于
std::atomic<>
从而提供a vlue of that type with atomic operations
Standard Layout
在layout部分里已经介绍过了,如果一个类是Standard Layout类,那么该类的对象在内存上的分配是连续的。
standard layout类应该具有以下特点:
- 没有虚函数或者虚基类
- 所有的非static的data members都是相同的访问级别
- 所有的非static的data members都是standard layout类的对象
- 如果有基类,基类也是standard layout
- has no base classes of the same type as the first non-static data member.
- 满足以下两个条件之一:
(一)派生类没有非static成员,基类有,但又不可以同时继承于多个拥有non-static数据成员的基类
(二)如果继承于一个基类,则该基类不可有非static的data members
举个例子:
// 虽然SL不是trivial类,但却是standard layout类
struct SL
{// All members have same access:int i;int j;SL(int a, int b) : i(a), j(b) {} // User-defined constructor OK
};
当继承的基类也有非static数据成员时,该类不是standard layout类:
struct Base
{int i;int j;
};// Derived类不是standard layout类, std::is_standard_layout<<Derived> == false!
struct Derived : public Base
{int x;int y;
};struct Base2
{void Foo() {}
};// std::is_standard_layout<<Derived2> == true
struct Derived2 : public Base2
{int x;int y;
};
POD types
When a class or struct is both trivial and standard-layout, it is a POD (Plain Old Data) type. The memory layout of POD types is therefore contiguous and each member has a higher address than the member that was declared before it, so that byte for byte copies and binary I/O can be performed on these types. Scalar types such as int are also POD types. POD types that are classes can have only POD types as non-static data members.
如果一个class或stuct,既是trivial类,也是standard layout类,那么该类是POD类。
POD类是老版的C语言对类型的形容,实际上,它可以分为两个部分,trivial和standard layout,所以新的C++版本把POD进行了进一步细分,在C++20开始,废弃了is_pod<T>
对应的trait
对于POD类T,
new T()
is value-initialization(will value-initialize all members) ,andnew T
will not initialize the members (default-initialization).
举个代码的例子:
#include <type_traits>
#include <iostream>using namespace std;struct B
{protected:virtual void Foo() {}
};// A继承于一个有虚函数的基类,所以A既不是trivial也不是standard layout
struct A : B
{int a;int b;void Foo() override {} // Virtual function
};// Trivial but not standard-layout
struct C
{int a;
private:int b; // Different access control,成员访问权限不同
};// Standard-layout but not trivial
struct D
{int a;int b;D() {} //User-defined constructor, 有自定义的default ctor
};struct POD
{int a;int b;
};int main()
{cout << boolalpha;cout << "A is trivial is " << is_trivial<A>() << endl; // falsecout << "A is standard-layout is " << is_standard_layout<A>() << endl; // falsecout << "C is trivial is " << is_trivial<C>() << endl; // truecout << "C is standard-layout is " << is_standard_layout<C>() << endl; // falsecout << "D is trivial is " << is_trivial<D>() << endl; // falsecout << "D is standard-layout is " << is_standard_layout<D>() << endl; // truecout << "POD is trivial is " << is_trivial<POD>() << endl; // truecout << "POD is standard-layout is " << is_standard_layout<POD>() << endl; // truereturn 0;
}
Literal types
还有一个trait,叫is_literal<T>
,literal类型的类,其layout可以在Compile Time确定,具体有如下类型:
- void
- scalar types,比如int, double等
- references
- Arrays of void, scalar types or references
- A class that has a trivial destructor, and one or more constexpr constructors that are not move or copy constructors. Additionally, all its non-static data members and base classes must be literal types and not volatile.
四种类型的类的关系
POD、standard layout、trivial和literal type的关系应该是这样(我自己画的,不一定准确):
如何判断一个类的对象是否可以用memcpy来复制
根据前面的介绍,应该是需要该类为standard layout类,而查阅资料后发现,其实只要is_trivially_copyable<T>::value
返回true,即可,即使不满足standard layout,也可以使用memcpy,比如下面的类:
struct T {int i;
private:int j;
};
也就是说,不用满足standard layout的类,也可以使用memcpy和memcopy,在C++ Concurrency In Action(Second Edition)里提到:
Objects with trivial copy constructors, trivial copy assignment operators, and trivial destructors can be copied with memcpy or memmove
至于std::is_standard_layout
,则一般用于保证C++与其他语言(比如C语言)的内存分布一致。
std::is_standard_layou is useful for communicating with other languages (for creating language bindings to native C++ libraries e.g.), and that’s why a standard-layout class has the same memory layout of the equivalent C struct or union.
trivial、standard layout、POD和literal类型解析相关推荐
- 传值类型_what?你竟然不知道C#中的方法及参数的类型解析!那还不快来瞅瞅
前言 哈哈,今天来给大家讲解一下关于C#中方法及参数的几种类型解析,没有看过的朋友,可以仔细的来瞧瞧了! 那么,还是话不多说,直接给大家献上今天的干货. 一.方法中参数的类型 1.in型参数 int ...
- Python静态类型解析工具简介和实践
简介: Python是一门强类型的动态类型语言,开发者可以给对象动态指定类型,但类型不匹配的操作是不被允许的.动态类型帮助开发者写代码轻松愉快,然而,俗话说:动态一时爽,重构火葬场.动态类型也带来了许 ...
- 接收list参数_what?你竟然不知道C#中的方法及参数的类型解析!那还不快来瞅瞅...
更多精彩,请点击上方蓝字关注我们! 前言 哈哈,今天来给大家讲解一下关于C#中方法及参数的几种类型解析,没有看过的朋友,可以仔细的来瞧瞧了! 那么,还是话不多说,直接给大家先上今天的干货了. 一.方法 ...
- 字符串类型日期时间转换为Date类型解析转换异常java.text.ParseException: Unparseable date: “2019-09-27T18:31:31+08:00”
字符串类型日期时间转换为Date类型解析转换异常java.text.ParseException: Unparseable date: "2019-09-27T18:31:31+08:00& ...
- GPS GLONASS数据文件类型解析
GPS & GLONASS数据文件类型解析 一.GPS数据格式 RINEX格式现如今已成为GPS测量应用中的标准数据格式,目前应用最为广泛.最普遍的是RINEX格式的第2个版本,该版本能够用于 ...
- Python 静态类型解析工具简介和实践
一 背景 Python是一门强类型的动态类型语言,开发者可以给对象动态指定类型(动态),但类型不匹配的操作是不被允许的(强类型,如str和int两个变量无法相加). 动态类型帮助开发者写代码轻松愉快, ...
- 计算机专业英语祈使句,常见英语祈使句类型解析,分类对比轻松学
原标题:常见英语祈使句类型解析,分类对比轻松学 祈使句通常主语为第二人称you,但一般不出现主语,多用于命令.建议或者请求的句子. 动词原形 Help! 救命啊! Go this way, pleas ...
- 在线加载谷歌地图—lyrs类型解析
在线加载谷歌地图-lyrs类型解析 最近在用openlayers加载在线谷歌地图的时候总结了一下lyrs之后地图类型解析 m 标准路线图 r 某种改变的路线图(路线不明显) s 影像层(卫星图) y ...
- Django创建应用,app注册,Filed字段类型解析,魔术方法str使用。
这篇博客根据上文Django创建第一个项目- ,从而在项目中跟进创建一个应用,以及app的注册, 模型models中的filed字段类型解析, 魔术方法 str 的使用. 工具: pycharm202 ...
- Appstore app链接mt参数app类型解析
Appstore app链接mt参数app分类类型解析 对 mt=8 也很好奇不知道为什么添加.以下是经过各种搜找到的结果: mt 代表 meta-type,有效值如下: 1 Music 2 ...
最新文章
- c#中的模态对话框和非模态对话框
- python中的数字类型格式与运算_Python中的数字类型格式与运算
- sql中使用“where 1=1 and ....“ 到底影响效率吗,回答不会也永远不会
- QT-子线程或自定义类操作访问主界面UI控件的几种方法
- vue+element 封装公共js代码
- Leetcode--881. 救生艇
- linux代码、数据库备份
- 苹果确认部分AirPods Pro存在静电噪音等声音问题 将免费更换
- 六部门集中约谈8家网约车顺风车平台 要求加快合规步伐
- 新闻媒体是怎样使用计算机的,计算机技术在新闻上的应用
- 如何转置_数据转置用选择性粘贴,图片呢?
- Windows10 关闭自动更新
- Python collections 模块中的 deque(队列)
- 40线性映射07——线性变换的矩阵表示、线性变换与基的关系、线性变换坐标间的关系、线性变换在不同基下矩阵之间的关系、相似矩阵
- Java 常用工具类 - 校验银行卡号 BankCardUtils
- cad隐藏图层命令快捷键_CAD各种插件大全汇总,1G多绘图神器+快捷键命令大全,无套路分享...
- 产业链图谱:2021年中国显示器产业链图谱|产业链全景图
- sql脚本 windows导出 linux乱码,mysql query browser中文乱码的解决方法
- 深入理解prach的频域和时域数据
- Excel 多个条件同时重复时,自动标红
热门文章
- 虾皮shopee根据ID取商品详情 API 返回值说明
- 有关javaSE下载时,环境配置path不成功,在cmd命令中java,javac,java -version出现不是内部或外部命令的现象处理
- linux uwsgi 非root,只能以root身份运行uwsgi
- 小米电脑如何把计算机放桌面上,小米电脑怎么把此电脑放到桌面上
- rtsp开源视频播放器VideoLAN
- 科学家首次3D生物打印出血管化肿瘤,并成功使用免疫疗法治疗
- MySql主从复制 Master-slaver
- 深度学习之epoch
- 【多目标跟踪论文阅读笔记——JDE(Towards Real-Time Multi-Object Tracking)】
- 用html做一个分类目录网站,分类目录网站做外链