右值引用就是对一个右值进行引用的类型。因为右值不具名,所以我们只能通过引用的方式找到它
无论声明左值引用还是右值引用都必须立即进行初始化,因为引用类型本身并不具有所绑定对象的内存,只是该对象的一个别名。
看一下下面的代码
1 #include <iostream> 2 using namespace std; 3 4 int g_constructCount = 0; 5 int g_copyConstructCount = 0; 6 int g_destructCount = 0; 7 struct A 8 { 9 A() { 10 cout << "construct: " << ++g_constructCount << endl; 11 } 12 13 A(const A& a) 14 { 15 cout << "copy construct: " << ++g_copyConstructCount << endl; 16 } 17 18 ~A() 19 { 20 cout << "destruct: " << ++g_destructCount << endl; 21 } 22 }; 23 24 A GetA() 25 { 26 return A(); 27 } 28 29 int main() 30 { 31 A a = GetA(); 32 return 0; 33 }
如果在g++下编译时设置编译选项-fno-elide-constructors,则会得到如下的结果
从上面的例子可以看到,在没有返回值优化的情况下,拷贝构造函数调用了两次,一次是GetA()函数内部创建的临时对象,另一次是构造a对象产生的。
为了清楚地观察临时值,g++ test.c -o test.out,运行test.out得到结果
这是编译器默认优化的效果,但这不是C++标准,是各编译器的优化规则。如果我们修改int main为
int main()
{
A&& a=GetA();
return 0;
}
输出结果为
通过右值引用,比之前少了一次拷贝构造和一次析构,原因在于右值引用绑定了右值,让临时右值的生命周期延长了。