C++ 性能剖析 (二):值语义 (value semantics)
Value Semantics (值语义) 是C++的一个有趣的话题。
什么是值语义? 简单的说,所有的原始变量(primitive variables)都具有value semantics. 也可以说,它们可以对应传统数学中的变量。有人也称它为POD (plain old data), 也就是旧时的老数据(有和 OOP 的新型抽象数据对比之意)。
对一个具有值语义的原始变量变量赋值可以转换成内存的bit-wise-copy。
对于用户定义的类呢?我们说,如果一个type X 具有值语义, 则:
1)X 的size在编译时可以确定。
这一点看似自然,其实在C++里有许多变量的size编译时无法确定。比如我在reference 三位一体里提到的polymorphic 变量,因为是“多身份”的,其(内容)的size是动态的。
2)将X的变量x,赋值与另一个变量y,无须专门的 = operator,简单的bit-wise-copy 即可。
3)当上述赋值发生后,x和y脱离关系:x 和 y 可以独立销毁, 其内存也可以独立释放。
了解第三点很重要,比如下面的class A就不具备值语义:
class A
{
char * p;
public:
A() { p = new char[10]; }
~A() { delete [] p; }
};
A 满足1和2,但不满足3。因为下面的程序会出错误:
Foo()
{
A a;
A b = a;
} // crash here
改进的方法是定义一个A::operator=(constA &),并且用reference counting 的技术来保护指针,实现起来并不简单。所以我们说一旦一个class 失去了value semantics, 它也就失去了简单明了的 = 语义。
从上面的分析可以得出结论,value semantics 有个简单的 = , 也正是数学意义上的 = 。
学过Java, C#, 和JavaScript的程序员都知道,这些语言里的object都不具有值语义,因为它们都是指针,= 并不copy内容。也不满足条件3。
那么value semantics 对C++性能有什么影响呢?我觉得有以下几方面:
1)std 库是基于值语义 的。std container 包含的元素,都具有值语义. 不理解这一点,就不能正确使用std,也不会对std的性能,做出合理预期。
2)简单的bit-wise-copy 赋值语句一般会提高赋值性能,因为它不需要特殊的 = operator 了。在使用std container 时,会有大量的copy 或assignment。 bit-wise-copy对于小的变量通常比函数划算得多。
3)具有值语义的,size 不大的变量,在stack里,作为auto变量,传递,拷贝,释放全部和原始变量的用法完全一致,既好用,一般也具有优良的性能。动态语言缺乏这个(值语义)的语言构造和能力,(C# 有有限地支持:c# struct),所以速度上很难优化。
4)注意,在设计具有值语义的类时,不要保留无用的destructor. destructor 的存在,使得你的类的语义和原始类有了本质的区别,C++ 编译会为此处心积虑地添加管理代码,使得一个简单的函数复杂化(会专门著文论证), 并且严重影响性能。这些当然是有附加值的,但是必须是设计需求的,而不是简单照搬的。
5)不要保留无用的destructor这点,对使用 std 时更重要。我会专门论述。不要有臃余无用的 destructor 对任何类都是适用的,而对于有大量 copy, assignment 的 std container 尤为重要!
那么,什么样的类没有值语义呢?我们不妨称这种型为 none-value-semantics type (NVST).
1)有virtual function 的类
2)包含NVST成员的类
3)NVST 的衍生类(derived classed)
4)定义了自己的 = operator 的类
5)继承 virtual 基类的衍生类
2014-6-21 西雅图
C++ 性能剖析 (二):值语义 (value semantics)的更多相关文章
- 快速学习C语言二: 编译自动化, 静态分析, 单元测试,coredump调试,性能剖析
上次的Hello world算是入门了,现在学习一些相关工具的使用 编译自动化 写好程序,首先要编译,就用gcc就好了,基本用法如下 gcc helloworld.c -o helloworld.o ...
- EMW 性能优化二之---并发配置
EMW 性能优化二之---并发配置 在前一个日志中写到交货的异步更新,对于RFUI RF的前台操作会提升效率,异步更新不用等待更新状态的返回,启用更新队列的方式执行(SM13). 下面再补全性能相关的 ...
- PDF.NET开发框架性能剖析
PDF.NET开发框架性能剖析 前俩天发布了 关于PDF.NET开发框架对Mysql Sqlite PostgreSQL数据库分页支持的个人看法 ,说明了本人对框架的一些介绍和看法.今天我们一起思考一 ...
- MySQL性能剖析工具(pt-query-digest)【转】
这个工具同样来自percona-toolkit 该工具集合的其他工具 MySQL Slave异常关机的处理 (pt-slave-restart) 验证MySQL主从一致性(pt-table-chec ...
- Wellner 自适应阈值二值化算法
参考文档: Adaptive Thresholding for the DigitalDesk.pdf Adaptive Thresholding Using the Integral I ...
- 对象语义与值语义、资源管理(RAII、资源所有权)、模拟实现auto_ptr<class>、实现Ptr_vector
一.对象语义与值语义 1.值语义是指对象的拷贝与原对象无关.拷贝之后就与原对象脱离关系,彼此独立互不影响(深拷贝).比如说int,C++中的内置类型都是值语义,前面学过的三个标准库类型string,v ...
- 二值法方法综述及matlab程序
在某些图像处理当中一个关键步是二值法,二值化一方面能够去除冗余信息,另一方面也会使有效信息丢失.所以有效的二值化算法是后续的处理的基础.比如对于想要最大限度的保留下面图的中文字,以便后续的定位处理. ...
- adaptiveThreshold自适应二值化源码分析
自适应二值化介绍: 二值化算法是用输入像素的值I与一个值C来比较,根据比较结果确定输出值. 自适应二值化的每一个像素的比较值C都不同,比较值C由这个像素为中心的一个块范围计算在减去差值delta得到. ...
- XNOR-Net:二值化卷积神经网络
https://www.jianshu.com/p/f9b015cc4514 https://github.com/hpi-xnor/BMXNet BMXNet:基于MXNet的开源二值神经网络实现 ...
随机推荐
- android 状态栏(StatusBar)
一.SystemUI 概述 自 android2.2 开始 , 原本存在与 framework-res.apk 中的状态栏和下拉通知栏界面控制被分割出一个单独的 apk 文件 , 命名为 System ...
- Spring boot将配置属性注入到bean类中
一.@ConfigurationProperties注解的使用 看配置文件,我的是yaml格式的配置: // file application.yml my: servers: - dev.bar.c ...
- Linux下的库操作工具-nm、ar、ldd、ldconfig和ld.so
Linux下的库操作工具-nm.ar.ldd.ldconfig和ld.so .nm [options] file 列出file中的所有符号 [option] -c 将符号转化为用户级的名字 -s 当用 ...
- COJ 0501 取数游戏(TPM)
取数游戏(TPM) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取 ...
- 网页a标签:导航制作 怎么让鼠标经过A标签的时候显示块状背景?
文章出处:http://dongguan.seosrx.net/website/6.html
- 《算法问题实战策略》-chaper17-部分和
数组上的一个基本优化——部分和: 对于一定长度的数组,我们想不断访问这个数组上的某个区间的和,我们能够怎么做呢?这里先不去谈一些数据结构在这个问题上的优化处理.首先我们最简单的一个方法就是穷举出所有区 ...
- java笔记7之录入
1 为了让程序的数据更符合开发的数据,我们就加入了键盘录入. 让程序更灵活一下. 那么,我们如何实现键盘数据的录入呢? A:导包 格式: ...
- OpenRisc-41-or1200的cache模块分析
引言 为CPU提供足够的,稳定的指令流和数据流是计算机体系结构设计中两个永恒的话题.为了给CPU提供指令流,需要设计分支预测机构,为了给CPU提供数据流,就需要设计cache了.其实,无论是insn还 ...
- .NET页面301跳转处理
//301跳转Response.Status = "301 Moved Permanently";Response.AddHeader("Location", ...
- Redis源代码分析(三)---dict哈希结构
昨天分析完adlist的Redis代码.今天立即马不停蹄的继续学习Redis代码中的哈希部分的结构学习,只是在这里他不叫什么hashMap,而是叫dict.并且是一种全新设计的一种哈希结构,他仅仅是通 ...