C++真正所谓的临时对象是不可见的——不会在你的源代码中出现。只要你产生一个non-heap object而没有为它命名,便诞生了一个临时对象。此等匿名对象通常发生于两种情况:
一是当隐式类型转换(implicit type conversions)被施行起来以求函数调用能够成功;
二是当函数返回对象的时候;
其实还有一种情况就是当你建立一个non-heap object对象,也就是无名对象的时候。
这里举一个常见的容易忽视的错误:
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
string s1("a"),s2("b");
const char * s = (s1+s2).c_str();
printf("%s\n",s);
}
这个程序运行的时候你可能会得到正确的结果,但事实上这里的做法是不安全的,s1+s2产生的临时对象会在表达式的结尾被析构,所以如果跟踪堆栈会发现在print语句中s的内存空间已经指向未知地址了。
这里针对3种会产生临时对象的情况举例进行说明:
1.隐式类型转换
void uppercasify(string& str);
// changes all chars in str to upper case
char subtleBookPlug[] = "Effective C++";
uppercasify(subtleBookPlug); //error!!!
因为要使函数调用成功,必须将subtleBookPlug转换成string类型,而编译器认为你要改变的subtleBookPlug,而类型转换后将产生一个类型为string的临时对象,而在void uppercasify(string& str)中,被改变的将是这个临时对象,而不是subtleBookPlug,这显然不是程序员所期望的,所以C++明智地禁止了这种行为
2.函数返回对象
#include <iostream>
using namespace std;
int func() {
int itgr;
return itgr;
}
int main(int argc, char *argv[]) {
int in;
in = func();
}
函数中的返回值会以值拷贝的形式拷贝到被调用函数栈中的一个临时对象。这里表达式func()创建了一个临时对象,用来存储func()函数返回的对象,临时对象由func()返回的itgr对象拷贝构造,临时对象赋值给in后,赋值表达式结束,临时对象被析构。所以这里就有一个问题。
int& intref = func();
如果用一个临时对象去初始化intref引用,一旦该表达式执行结束,临时对象的生命周期也就结束了,引用的实体已经不复存在。
3.no heap的对象
int& intref = int(5);
int itgr = int(5);
Calculate(int(5));
上述表达式中的临时对象用来完成初始化引用,拷贝构造和实参等作用。
关于临时对象生命周期的延长等问题,后面的博客再更新吧,越来越觉得C++真心麻烦…
原文地址:http://blog.csdn.net/john_cdy/article/details/46356323