第四章,效率

条款19 了解临时对象的来源

概述: 临时对象并不是写在函数内部的对象,那是局部对象。真正的临时对象是不可见的,不会出现在源码中。临时对象只会产生于这两种情况下:

1、隐式类型转换被施行起来以求函数调用能够成功;
2、当函数返回对象时

临时对象的产生,情况1: 以求函数调用能够成功

//计算某字串中某字符出现的次数
size_t countChar(const string& str, char ch);

char buffer[MAX_STRING_LEN];
char c;

//读入一个char和一个string,利用setw避免读入string时产生缓冲区满溢的情况
cin >> c >> setw(MAX_STRING_LEN) >> buffer;

cout << "There are " << countChar(buffer, c)
<< " occurrences of the character " << c
<< " in " << buffer << endl;

/*
countChar的str参数类型是const string& str,但是传入的buffer的一个字符数组,
编译器必须将字符数组类型转换为const string才能正常调用函数countChar,
就是在这个过程中,编译器会生成一个临时对象string,并以buffer为自变量调用构造函数,
countChar的str参数会被绑定与此string临时对象上,当函数countChar返回,此临时对象会被自动销毁。

显然,这样的临时对象是非必要的,应该避免。

此外,只有当对象是以by value(传值)方式传递,或是传递给一个reference-to-const 参数时,
这样的转换以及后面产生临时对象才会发生;
如果对象被传递给一个reference-to-non-const参数,并不会发生此类转换,但会报错!
*/
void uppercasify(string& str); //将str中的所有chars改为大写

char subtleBookPlug[] = "Effective C++"
uppercasify(subtleBookPlug); //错误!

//这里编译器不会进行转型操作,因为string& str期望是通过引用修改原来的字串,而不是修改一个为了满足函数调用而创建的临时对象;这是设计上的有效防范。

临时对象的产生,情况2: 函数返回对象

const Number operator+(const Number& lhs,
const Number& rgh);
/*
operator+返回一个Number临时对象,当调用时,便得为此付出新的构造和析构成本;
为避免这份成本,常见也是最有用的就是“返回值优化”
*/

总结:

临时对象可能很耗成本,应该尽可能消除它们。
因此,有依据的找出这些情况非常重要,任何时候看到一个reference-to-const参数,就既有可能会参数一个临时对象产生出来绑定到该参数上。
任何时候,只要看到函数返回一个对象,就会产生临时对象。