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)的更多相关文章

  1. 快速学习C语言二: 编译自动化, 静态分析, 单元测试,coredump调试,性能剖析

    上次的Hello world算是入门了,现在学习一些相关工具的使用 编译自动化 写好程序,首先要编译,就用gcc就好了,基本用法如下 gcc helloworld.c -o helloworld.o ...

  2. EMW 性能优化二之---并发配置

    EMW 性能优化二之---并发配置 在前一个日志中写到交货的异步更新,对于RFUI RF的前台操作会提升效率,异步更新不用等待更新状态的返回,启用更新队列的方式执行(SM13). 下面再补全性能相关的 ...

  3. PDF.NET开发框架性能剖析

    PDF.NET开发框架性能剖析 前俩天发布了 关于PDF.NET开发框架对Mysql Sqlite PostgreSQL数据库分页支持的个人看法 ,说明了本人对框架的一些介绍和看法.今天我们一起思考一 ...

  4. MySQL性能剖析工具(pt-query-digest)【转】

    这个工具同样来自percona-toolkit 该工具集合的其他工具 MySQL Slave异常关机的处理 (pt-slave-restart)  验证MySQL主从一致性(pt-table-chec ...

  5. Wellner 自适应阈值二值化算法

    参考文档: Adaptive Thresholding for the DigitalDesk.pdf       Adaptive Thresholding Using the Integral I ...

  6. 对象语义与值语义、资源管理(RAII、资源所有权)、模拟实现auto_ptr<class>、实现Ptr_vector

    一.对象语义与值语义 1.值语义是指对象的拷贝与原对象无关.拷贝之后就与原对象脱离关系,彼此独立互不影响(深拷贝).比如说int,C++中的内置类型都是值语义,前面学过的三个标准库类型string,v ...

  7. 二值法方法综述及matlab程序

    在某些图像处理当中一个关键步是二值法,二值化一方面能够去除冗余信息,另一方面也会使有效信息丢失.所以有效的二值化算法是后续的处理的基础.比如对于想要最大限度的保留下面图的中文字,以便后续的定位处理. ...

  8. adaptiveThreshold自适应二值化源码分析

    自适应二值化介绍: 二值化算法是用输入像素的值I与一个值C来比较,根据比较结果确定输出值. 自适应二值化的每一个像素的比较值C都不同,比较值C由这个像素为中心的一个块范围计算在减去差值delta得到. ...

  9. XNOR-Net:二值化卷积神经网络

    https://www.jianshu.com/p/f9b015cc4514 https://github.com/hpi-xnor/BMXNet  BMXNet:基于MXNet的开源二值神经网络实现 ...

随机推荐

  1. 转:Google论文之一----Bigtable学习翻译

    文章来自于:http://www.cnblogs.com/geekma/archive/2013/05/30/3108391.html Bigtable研究 摘要 Bigtable是一个用于管理结构型 ...

  2. 转:Hprose for php(二)——服务器

    文章来自于:http://blog.csdn.net/half1/article/details/21252879 本文将介绍Hprose for php服务器的更多细节 1.发布服务 Hprose提 ...

  3. 14.4.1 Buffer Pool

    14.4.1 Buffer Pool buffer pool 是一个主人的内存区域 InnoDB caches 表和index 数据. buffer pool 允许经常访问的数据直接从内存里处理,加快 ...

  4. POJ2485 Highways(最小生成树)

    题目链接. 分析: 比POJ2253要简单些. AC代码: #include <iostream> #include <cstdio> #include <cstring ...

  5. 【转】Android中的内存管理--不错不错,避免使用枚举类型

    原文网址:http://android-performance.com/android/2014/02/17/android-manage-memory.html 本文内容翻译自:http://dev ...

  6. JAVA中的Transient

    Java中的transient,是用于声明序列化的时候不被存储的. 例子: package ThreadTest; /** * Created with IntelliJ IDEA. * User: ...

  7. UIAlertController 的使用——NS_CLASS_AVAILABLE_IOS(8_0)

    UIAlertView 随着苹果上次iOS 5的发布,对话框视图样式出现在了我们面前,直到现在它都没有发生过很大的变化.下面的代码片段展示了如何初始化和显示一个带有“取消”和“好的”按钮的对话框视图. ...

  8. JSP学习笔记(一):JDK的安装及环境变量的配置

    一.JDK的安装. JDK可以在Oracle(甲骨文)的官网下载,连接地址:http://www.oracle.com/technetwork/java/javase/downloads/index- ...

  9. 【web开发问题】HTTP请求POSTDATA中包含多层对象如何获取?

    postdata如下: TravelerID=&ChineseName=***&PhoneNumber=&IDNumber=&IsCommonUse=&Gues ...

  10. C# 自己定义 implicit和explicit转换

    explicit 和 implicit 属于转换运算符,如用这两者能够让我们自己定义的类型支持相互交换explicti 表示显式转换.如从 A -> B 必须进行强制类型转换(B = (B)A) ...