什么是临时对象?
? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象.
通常出现在以下两种情况:
(1)为了使函数调用成功而进行隐式类型转换的时候。
? 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即刻自动销毁。如下
int countChar (const string& str, char ch);
char buffer[];
char c;
countChar (buffer, c);
我们看的第一个参数为char[],而函数的参数类型为const string&,参数不一致,看看能否进行隐式转化,string类有个构造函数是可以作为隐式转化函数的。那么编译器会产生一个string的临时变量,以buffer为参数进行构造,那么countChar中的str参数会绑定到此临时变量上,直到函数返回时销毁。
注意这样的转化只会出现在两种情况下:函数参数以传值(by value)的方式传递 或者 对象被传递到一个 reference-to-const 参数上。
传值方式:
int countChar (string str, char ch);
string buffer;
char c;
countChar (buffer, c);
? 这种方法会调用string的拷贝构造函数生成一个临时变量,再将这个临时变量绑定到str上,函数返回时进行销毁。
传常量引用:
? 开始的实例即时属于这种情况,但一定强调的是传递的是const型引用,如将开始函数的原型改为
int countChar (string& str, char ch);
? 下面调用相同,编译器会报错!为什么C++设计时要求 当对象传递给一个reference-to-non-const 参数不会发生隐式类型转化呢?
? 下面的实例可能向你说明这样设计的目的:
void toUpper (string& str);
char buffer[] = "hazirguo";
toUpper(buffer);
? 如果编译器允许上面的传递完成,那么,会生成一个临时对象,toUpper函数将临时变量的字符转化为大写,返回是销毁对象,但是对buffer内容毫无影响!程序设计的目地是期望对“非临时对象”进行修改,而如果对reference-to-non-cosnt对象进行转化,函数只会对临时变量进行修改。这就是为什么C++中要禁止non-const-reference参数产生临时变量的原因了。
(2)当函数返回对象的时候。
? 当函数返回一个对象时,编译器会生成一个临时对象返回,如声明一个函数用来合并两个字符串:
const string strMerge (const string s1, const string s2);
大多时候是无法避免这样的临时变量产生的,但是现代编译器可以将这样的临时变量进行优化掉,这样的优化策略中,有个所谓的“返回值优化”
总结:
临时对象有构造和析构的成本,影响程序的效率,因此尽可能地消除它们。而更为重要的是很快地发现什么地方会生成临时对象: