1.定义
临时量:编译器在计算表达式结果时创建的无名对象。为某表达式创建了一个临时值,此临时值将一直存在到包含有该表达式的最大表达式计算完成为止。临时量包括非引用返回的函数返回值、表达式。临时量没有名字,不能取地址,不能对临时量进行非常量引用,临时量是一个纯右值。
表达式:表达式是由一个或多个运算对象和运算符组成,对表达式求值将得到一个结果,运算符有一元运算符、二元运算符、多元运算符(函数调用是特殊的运算符)。
如:
int a = 10 + 20; //10+20是一个表达式
//等价于
int temp = 10 + 20;
int a = temp;
//函数调用也是一个表达式,求值结果是一个右值,是临时量。
max(10, 20);
//等价于
int temp = max(10, 20); //临时量在这条语句执行完之后销毁
2.临时量的类型
临时量是一个变量,但却不能被普通引用绑定,只能被常量引用绑定:
int &r = 10 + 20; //错误:非常量引用的初始值必须是左值,但临时量是一个右值
const &r = 10 + 20; //正确:常量引用可以绑定任意表达式
这并不是因为临时量是一个常量,其实临时量是一个变量。而是因为非常量引用的意义来的决定的:
如果我们使用普通引用绑定一个对象,那么就是告诉编译器,我们想改变这个对象。但是,绑定一个临时量没有意义,因为临时量的生存期在这条语句结束后就被销毁,因此,当一个普通引用绑定了一个临时对象之后,这个临时对象便销毁了,我们无法对其进行操作,因此绑定一个临时量是没有意义的。
但常量引用可以绑定到临时量上,是因为常量引用不会改变绑定对象的值,因此,不管绑定的是临时量还是对象都无所谓。
3.临时量的生成方式
临时量有两种生成方式:隐式生成方式和显式生成方式。
①隐式生成方式:
- 表达式的结果是一个临时量,如:
int a = 10 + 20; //10+20是一个表达式,其结果是一个临时量
//等价于
int temp = 10 + 20;
int a = temp;
string s1, s2;
string s3 = s1 + s3; //string的+操作其实是个函数重载,生成临时量
//等价于
string temp = s1 + s2;
string s3 = temp;
- 非引用返回的函数返回值会产生临时对象量,如:
//X是一个自定义类型,且有重载的比较符
X getMax(X &lhs, X &rhs) {
return lhs > rhs ? lhs : rhs;
}
X a, b;
X ret = getMax(a, b);
//相当于
X a, b;
X &lhs = a, &rhs = b;
X temp = lhs > rhs ? lhs : rhs;
X ret = temp; //temp是临时量,这条语句结束后销毁
- 类型转换时会产生临时量,如:
int a = 3.14; //3.14是double型,而a是int型类型不同会产生临时量
//等价于
int temp = 3.14;
int a = temp;
//内置类型X,有构造函数X(int val);
X a = 10; //10是int型,而a是X型,会发生隐式类型转换产生临时量
//等价于
X temp(10);
X a = temp;
②显式生成方式:
- 对内置类型来说,如:
int a = int(); //显式生成临时量给a赋值
//等价于
int temp = 0;
int a = temp;
- 对自定义类型来说,通过与参数相匹配的直接构造函数生成,如:
//内置类型X,有构造函数X(int val);
X a = X(10); //显式生成临时量给a赋值
//等价于
X temp(10);
X a = temp;