您的位置:首页 > 其它

了解临时对象的来源 (深刻理解为什么不能返回一个临时变量的引用)

2016-04-13 10:54 483 查看

什么是临时对象?

C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象.

通常出现在以下两种情况:

(1)为了使函数调用成功而进行隐式类型转换的时候

传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁。如下例:

//计算字符ch在字符串str中出现的次数
intcountChar(conststring&str,charch);
charbuffer[];
charc;
//调用上面的函数
countChar(buffer,c);



我们看的第一个参数为char[],而函数的参数类型为conststring&,参数不一致,看看能否进行隐式转化,string类有个构造函数是可以作为隐式转化函数(参见5)的。那么编译器会产生一个string的临时变量,以buffer为参数进行构造,那么countChar中的str参数会绑定到此临时变量上,直到函数返回时销毁。

注意这样的转化只会出现在两种情况下:函数参数以传值(byvalue)的方式传递或者对象被传递到一个reference-to-const参数上。

传值方式:



intcountChar(stringstr,charch);
stringbuffer;
charc;
//参数通过传值方式传递
countChar(buffer,c);



这种方法会调用string的拷贝构造函数生成一个临时变量,再将这个临时变量绑定到str上,函数返回时进行销毁。

传常量引用:

开始的实例即时属于这种情况,但一定强调的是传递的是const型引用,如将开始函数的原型改为



intcountChar(string&str,charch);


下面调用相同,编译器会报错!为什么C++设计时要求当对象传递给一个reference-to-non-const参数不会发生隐式类型转化呢?

下面的实例可能向你说明这样设计的目的:



//声明一个将str中字符全部转化为大写
voidtoUpper(string&str);
charbuffer[]="hazirguo";
toUpper(buffer);//error!!非const引用传递参数不能完成隐式转化



如果编译器允许上面的传递完成,那么,会生成一个临时对象,toUpper函数将临时变量的字符转化为大写,返回是销毁对象,但是对buffer内容毫无影响!程序设计的目地是期望对“非临时对象”进行修改,而如果对reference-to-non-cosnt对象进行转化,函数只会对临时变量进行修改。这就是为什么C++中要禁止non-const-reference参数产生临时变量的原因了。

(2)当函数返回对象的时候

当函数返回一个对象时,编译器会生成一个临时对象返回,如声明一个函数用来合并两个字符串:



conststringstrMerge(conststrings1,conststrings2);



大多时候是无法避免这样的临时变量产生的,但是现代编译器可以将这样的临时变量进行优化掉,这样的优化策略中,有个所谓的“返回值优化”,下一篇具体讲解。


总结:

临时对象有构造和析构的成本,影响程序的效率,因此尽可能地消除它们。而更为重要的是很快地发现什么地方会生成临时对象:


当我们看到一个reference-to-const参数时,极可能一个临时对象绑定到该参数上;

当我们看到函数返回一个对象时,就会产生临时对象。

转载于

/article/5122589.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: