More Effective C++ ——019_理解临时对象的来源

来源:互联网 发布:淘宝店铺装修数据包 编辑:程序博客网 时间:2024/05/01 14:41

条款十九:理解临时对象的来源

什么叫临时变量?先看下面这个例子:  

template<class T>  void swap(T& object1, T& object2)  {   T temp = object1;   object1 = object2;   object2 = temp;  }

一般人把temp叫做临时变量。但对C++而言,temp根本不是临时变量,它是一个函数的局部对象。
在C++中真正的临时对象是看不见的,它们不出现在源代码中。建立一个没有命名的非堆(non-heap)对象会产生临时对象,因为局部对象生命周期短数据易被销毁,没有临时对象(副本)产生则数据传递不了
临时对象产生时机:
1) 函数参数调用时(为了使函数成功调用而进行隐式类型转换)
2)函数返回对象时


临时对象产生开销

产生临时对象带来构造和析构函数调用的开销,对程序的影响不可忽悠,有两个方法可以消除。
注:一种是重新设计你的代码,不让发生这种类型转换。(见条款5)。另一种方法是通过修改软件而不再需要类型转换(见条款21)。


C++中仅当通过传值(by value)方式传递对象或传递常量引用(reference-to-const)参数时,才会发生这些类型转换。当传递一个非常量引用(reference-to-non-const)参数对象,就不会发生。


函数参数调用时

a)by value——add(T a,T b),add(T* a,T* b)
T不能是数组类型,数组作为函数参数会退化为指针类型就是很好证明(复制指针只需要4个字节内存),但拷贝数组消耗大量内存及降低效率。

b)reference-to-const——add(const T& a)
const 要求不能改变被引用对象的值。所以必须要有临时对象产生,否则,会修改到实参的数值。

c)reference-to-non-const——add( T& a)
没有const 修饰时,引用要求能修改被引用的实参的数值。如果有临时对象产生,则达不到修改实参的效果。


函数返回对象

因为局部对象生命周期有限,无法传递内容出去,需要建立副本。
  
如果你不想付出这样的开销。对于这种函数, 

const Number operator+(const Number& lhs,const Number& rhs);

你可以切换到operator=,而避免开销(见条款22)。
但对于大多数返回对象的函数来说,无法切换到不同的函数,从而没有办法避免构造和释放返回值。至少在概念上没有办法避免它。
可喜的是概念和现实之间又有一个黑暗地带,叫做优化,有时你能以某种方法编写返回对象的函数,以允许编译器优化临时对象。这些优化中,最常见和最有效的是返回值优化(见条款20)


总结:临时对象是有开销的,所以你应该尽可能地去除它们,然而更重要的是训练自己寻找可能建立临时对象的地方。在任何时候只要见到常量引用(reference-to-const)参数,就存在建立临时对象而绑定在参数上的可能性。在任何时候只要见到函数返回对象,就会有一个临时对象被建立(以后被释放)。学会寻找这些对象构造,你就能显著地增强透过编译器表面动作而看到其背后开销的能力。

0 0
原创粉丝点击