`

C++中的临时对象

    博客分类:
  • C++
阅读更多
程序员间交谈时,经常把仅仅需要一小段时间的变量称为临时变量。例如在下面这段swap(交换)例程里:
template<class T>
void swap(T& object1, T& object2)
{
T temp = object1;
object1 = object2;
object2 = temp;
}
   
    通常把temp叫做临时变量。不过就C++而言,temp根本不是临时变量,它只是一个函数的局部对象。
    在C++中真正的临时对象是看不见的,它们不出现在我们的源代码中。建立一个没有命名的非堆(non-heap)对象会产生临时对象。这种未命名的对象通常在两种条件下产生:为了使函数成功调用而进行隐式类型转换和函数返回对象时。理解如何和为什么建立这些临时对象是很重要的,因为构造和释放它们的开销对于程序的性能来说有着不可忽视的影响。
   
    首先考虑为使函数成功调用而建立临时对象这种情况。当传送给函数的对象类型与参数类型不匹配时会产生这种情况。例如一个函数,它用来计算一个字符在字符串中出现的次数:
// 返回ch在str中出现的次数
size_t countChar(const string& str, char ch);
char buffer[MAX_STRING_LEN];
char c;
// 读入到一个字符和字符串中,用setw避免缓存溢出,当读取一个字符串时
cin >> c >> setw(MAX_STRING_LEN) >> buffer;
cout << "There are " << countChar(buffer, c)
     << " occurrences of the character " << c
<< " in " << buffer << endl;
   
    看一下countChar的调用。第一个被传送的参数是字符数组,但是对应函数的正被绑定的参数的类型是const string&。仅当消除类型不匹配后,才能成功进行这个调用,编译器很乐意替你消除它,方法是建立一个string类型的临时对象。通过以buffer做为参数调用string的构造函数来初始化这个临时对象。countChar的参数str被绑定在这个临时的string对象上。当countChar返回时,临时对象自动释放。
   
    这样的类型转换很方便(尽管很危险),但是从效率的观点来看,临时string对象的构造和释放是不必要的开销。通常有两个方法可以消除它。一种是重新设计代码,不让发生这种类型转换。另一种方法是通过修改软件而不再需要类型转换。
   
    仅当通过传值(by value)方式传递对象或传递常量引用(reference-to-const)参数时,才会发生这些类型转换。当传递一个非常量引用(reference-to-non-const)参数对象,就不会发生。考虑一下这个函数:
void uppercasify(string& str);               // 把str中所有的字符
// 改变成大写
   
    在字符计数的例子里,能够成功传递char数组到countChar中,但是在这里试图用char数组调用upeercasify函数,则不会成功:
char subtleBookPlug[] = "Effective C++";
uppercasify(subtleBookPlug);                // 错误!
   
    没有为使调用成功而建立临时对象,为什么呢?
    假设建立一个临时对象,那么临时对象将被传递到upeercasify中,其会修改这个临时对象,把它的字符改成大写。但是对subtleBookPlug函数调用的真正参数没有任何影响;仅仅改变了临时从subtleBookPlug生成的string对象。无疑这不是程序员所希望的。程序员传递subtleBookPlug参数到uppercasify函数中,期望修改subtleBookPlug的值。当程序员期望修改非临时对象时,对非常量引用(references-to-non-const)进行的隐式类型转换却修改临时对象。这就是为什么C++语言禁止为非常量引用(reference-to-non-const)产生临时对象。这样非常量引用(reference-to-non-const)参数就不会遇到这种问题。
   
    建立临时对象的第二种环境是函数返回对象时。例如operator+必须返回一个对象,以表示它的两个操作数的和。例如给定一个类型Number,这种类型的operator+被这样声明:
const Number operator+(const Number& lhs,const Number& rhs);
   
    这个函数的返回值是临时的,因为它没有被命名;它只是函数的返回值。必须为每次调用operator+构造和释放这个对象而付出代价。
   
    通常我们不想付出这样的开销。对于这种函数,可以切换到operator=,而避免开销。不过对于大多数返回对象的函数来说,无法切换到不同的函数,从而没有办法避免构造和释放返回值。至少在概念上没有办法避免它。然而概念和现实之间又一个黑暗地带,叫做优化,有时能以某种方法编写返回对象的函数,以允许编译器优化临时对象。这些优化中,最常见和最有效的是返回值优化。
   
    综上所述,临时对象是有开销的,所以应该尽可能地去除它们,然而更重要的是训练自己寻找可能建立临时对象的地方。在任何时候只要见到常量引用(reference-to-const)参数,就存在建立临时对象而绑定在参数上的可能性。在任何时候只要见到函数返回对象,就会有一个临时对象被建立(以后被释放)。学会寻找这些对象构造,就能显著地增强透过编译器表面动作而看到其背后开销的能力。

分享到:
评论

相关推荐

    深入c++中临时对象的析构时机的详解

    c++中,临时对象一旦不需要,就会调用析构函数,释放其占有的资源;而具名对象则是与创建的顺序相反,依次调用析构函数。 c++源码: 代码如下:class X {public: int i; int j; ~X() {} X() {}}; int main() { X...

    C++l临时对象

    ### C++中的临时对象 #### 一、引言 在C++编程中,临时对象是一个非常重要但又常常被忽视的概念。这些对象虽然不直接出现在源代码中,但在编译器生成的目标代码中却扮演着至关重要的角色。了解临时对象如何产生、...

    C++中的引用

    常引用在保护函数参数不被修改时特别有用,同时也解决了C++中临时对象通常为const类型的问题,防止了非const引用尝试修改const对象的非法操作。 在实际编程中,理解并熟练运用引用,尤其是常引用,能够编写出更加...

    详解C++ 中的临时对象

    在C++编程语言中,临时对象(Temporary Object)是指在表达式中为了完成特定操作而临时创建的对象。这些对象通常不被程序员直接命名,而是由编译器在幕后生成并管理。临时对象主要出现在以下几个场景: 1. **无名...

    深入解析C++中的临时变量

    深入解析C++中的临时变量:理解其本质与作用 在C++编程中,临时变量扮演着至关重要的角色,尽管它们通常在代码中“隐身”,但它们的存在极大地影响着程序的性能和行为。本文将深入探讨C++中的临时变量,从操作系统...

    深度探索C++对象模型 PDF中文清晰版

    《深度探索C++对象模型》专注于C++面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承。这本书让你知道:一旦你能够了解底层实现模型,你的程序代码将获得...

    C++临时对象详解[收集].pdf

    C++中的临时对象是指在表达式中为了完成特定任务而临时创建的对象,它们在程序运行过程中通常是不可见的,并且生命期很短。临时对象的创建可能会带来性能上的开销,尤其是在涉及拷贝构造函数或者多态性时。在本文中...

    C++中的临时变量

    ### C++中的临时变量 #### 一、引言 在C++编程中,临时变量是一个非常重要但又常常被忽视的概念。这些特殊的变量由编译器自动生成,用于处理某些特定情况下的数据操作,如函数调用时的参数传递或者作为函数返回值...

    C++临时性对象的生命周期详细解析

    下面的例子中,`f(A())`返回一个引用,该引用绑定到一个临时对象,即使临时对象作用域结束,只要引用还在使用,临时对象就不会被销毁。 ```cpp const A& f(const A& a){ return a; } int main(){ { const A& a ...

    C++单向按值传递(产生临时对象) 双向按引用传递(不产生临时对象不占任何内存).rar

    在C++中,当一个对象作为参数按值传递时,会创建该对象的一个临时副本。这个过程可能导致性能上的开销,特别是在传递大型数据结构时,因为需要复制整个对象的内存空间。 例如: ```cpp void swap(int a, int b) { ...

    深度探索C++对象模型(中文版&英文版)

    本书探讨了大量的C++面向对象程序设计的底层运作机制,包括构造函数,函数,临时对象,继承,虚拟,模板的实例化,异常处理,运行期类型识别等,另外还介绍了一些在实现C++对象模型过程中做出的权衡折衷.喜欢刨根问底的C++...

    深度探索C++对象模型读书笔记

    - **临时对象的管理**:讨论临时对象的生命周期及其如何被正确处理。 #### 结语 通过以上内容,我们可以看出C++对象模型是一个庞大且复杂的主题。理解这些基础知识不仅可以帮助我们编写出更高效、更安全的代码,还...

    C++有子对象的派生类的构造函数

    这样做可以避免临时对象的创建和销毁,从而提高性能。例如: ```cpp class Base { public: Base(int val) : value(val) {} private: int value; }; class Derived : public Base { public: Derived(int baseVal...

    Effective C++ 中文带目录

    Meyers在书中不仅介绍了如何避免不必要的对象构造和复制,还涉及到了如何合理利用临时对象、返回值优化等高级技术。例如,使用引用传递代替值传递可以减少不必要的对象构造,而当需要返回一个临时对象时,如果返回...

    深入探索C++对象模型-总结笔记.pdf

    本书专注于C++面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承。这本书让你知道:一旦你能够了解底层实现模型,你的程序代码将获得多么大的效率。...

    详解C++ 临时量与临时对象及程序的相关优化

    在C++编程中,临时量和临时对象是两个重要的概念,它们在程序执行过程中起着关键的作用。本文将深入探讨这两个概念以及相关的程序优化策略。 首先,临时量是指在表达式中生成的、用于临时存储结果的量。对于内置...

Global site tag (gtag.js) - Google Analytics