Thinking in C++ P368页关于Temporaries的论述中写道:But there is one thing about temporaries:they’re automatically const. Because you usually won’t be able to get your hands on a temporary object,telling it to do something that will change that temporary is almost certainly a mistake because you won’t be ableto use that information. By making all temporaries automatically const, the compiler informs you when you make that mistake.
意思是:temporary object自动具有const属性(后面所做实验证明这句话并不严谨,不过也可能是我对此句的理解有误)。因为通常你不能让一个temporary object去做一些会改变自己的事情,这是错误的,因为你根本就无法使用这些信息。通过让所有的temporaries 自动成为const,当你犯错时编译器会告知你。
但通过实验,正确的说法应该是:C++中对临时变量的引用必须进行const 引用。
临时变量:它在代码中看不到,但是确实存在。它就是临时对象---由编译器定义的一个没有命名的非堆对象。
临时变量产生的时机:
1. 函数调用类型转换
2.按值返回
如果一个参数是以一个非const引用传 入的,那么C++编译器就有理由相信我们传入的参数在函数中是可以被修改的,并且这个修改的变量在函数外也是可以使用的,但是如果我们把一个临时变量当成非const引用参数传进来,则由于临时变量的特殊性,对临时变量的修改在函数内部,而临时变量在使用完成后会释放,所以如果我们修改一个临时变量实际上没有意义的,因此C++编译器就加入了临时变量不能作为非const引用的这个语意限制,主要是限制这个非常规的用法的潜在错误。在编译期间就告诉你错误,比在运行时遇到问题要更为友好。
1.函数调用类型转换:
#include <iostream>
#include <string>
using namespace std;
void make_upper(string& s){}
int main(){
string s1("hello, world");
make_upper(s1);
cout << s1 << endl;
char text[] = "hello, world";
//make_upper(text); error! convert char* to string
cout << text << endl;
return 0;
}
改为const引用后不报错。
2.函数返回值
#include <iostream>
#include <string>
using namespace std;
class X {};
X f() { return X(); }
void g1(X&) {}
void g2(const X&) {}
int main(){
//g1(f()); error!
g2(f());
return 0;
}
但是临时变量具有const属性这一说法并不严谨,以下代码:
#include <iostream>
#include <string>
using namespace std;
class X {
int i;
public:
X (int ii = 100) : i(ii) {}
void inc(){
++i;
cout << "Now i is " << i << endl;
}
};
X f() { return X(); }
int main(){
f().inc();
return 0;
}
如果临时对象具有const属性,那么const对象不能调用非const成员函数,但是以上代码却能成功运行。
进一步的,可以将返回的对象赋给一个非常量对象,也可以对返回的对象进行赋值操作。
#include <iostream>
#include <string>
using namespace std;
class X {
int i;
public:
X (int ii = 100) : i(ii) { cout << "constructed addr is: " << this << endl; }
X& operator=(const X o){
i = o.i;
cout << "assignment happened" << endl;
return *this;
}
void inc(){
++i;
cout << "Now i is " << i << endl;
}
~X(){
cout << "deconstructed" << endl;
}
};
X f() { return X(); }
int main(){
f().inc();
X a = f();
cout << "a's addr is: " << &a << endl;
a.inc();
(f() = a).inc();
return 0;
}
运行结果为: