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的开源二值神经网络实现 ...
随机推荐
- 转:Google论文之一----Bigtable学习翻译
文章来自于:http://www.cnblogs.com/geekma/archive/2013/05/30/3108391.html Bigtable研究 摘要 Bigtable是一个用于管理结构型 ...
- 转:Hprose for php(二)——服务器
文章来自于:http://blog.csdn.net/half1/article/details/21252879 本文将介绍Hprose for php服务器的更多细节 1.发布服务 Hprose提 ...
- 14.4.1 Buffer Pool
14.4.1 Buffer Pool buffer pool 是一个主人的内存区域 InnoDB caches 表和index 数据. buffer pool 允许经常访问的数据直接从内存里处理,加快 ...
- POJ2485 Highways(最小生成树)
题目链接. 分析: 比POJ2253要简单些. AC代码: #include <iostream> #include <cstdio> #include <cstring ...
- 【转】Android中的内存管理--不错不错,避免使用枚举类型
原文网址:http://android-performance.com/android/2014/02/17/android-manage-memory.html 本文内容翻译自:http://dev ...
- JAVA中的Transient
Java中的transient,是用于声明序列化的时候不被存储的. 例子: package ThreadTest; /** * Created with IntelliJ IDEA. * User: ...
- UIAlertController 的使用——NS_CLASS_AVAILABLE_IOS(8_0)
UIAlertView 随着苹果上次iOS 5的发布,对话框视图样式出现在了我们面前,直到现在它都没有发生过很大的变化.下面的代码片段展示了如何初始化和显示一个带有“取消”和“好的”按钮的对话框视图. ...
- JSP学习笔记(一):JDK的安装及环境变量的配置
一.JDK的安装. JDK可以在Oracle(甲骨文)的官网下载,连接地址:http://www.oracle.com/technetwork/java/javase/downloads/index- ...
- 【web开发问题】HTTP请求POSTDATA中包含多层对象如何获取?
postdata如下: TravelerID=&ChineseName=***&PhoneNumber=&IDNumber=&IsCommonUse=&Gues ...
- C# 自己定义 implicit和explicit转换
explicit 和 implicit 属于转换运算符,如用这两者能够让我们自己定义的类型支持相互交换explicti 表示显式转换.如从 A -> B 必须进行强制类型转换(B = (B)A) ...