一般的,我们最先接触的引用大多是诸如:
int val = 10;
int &ref = val;
上述的引用方式我们称为左值引用。
而右值引用发生在如下情况:
int val = 10;
int & ref = val + 1; //此句不合法,因为右值无法赋值给左值引用
const int& ref = val + 1;//合法
解释:资料说C++
中临时变量默认const
属性,所以只能传给const
的引用。规定右值不能绑定到非 const
限定的左值引用。异常对象另说;如果是右值引用或const左值
引用绑定的,那生存期延长为引用;否则到完全表达式结束销毁。还有默认初始化数组元素时延长到数组初始化结束
也就是说:
int main()
{
const int& a = 53;
}
也就是说,53是作为一个匿名的值被存放到一个栈中,而a
是53的那个别名。生命周期和引用相同。
当然我们也可以通过指针改变这个内存中的值。
int main()
{
const int& a = 53;
int *p = (int*)&a;
*p = 66; //53所在的那个地址的值(a)被修改成了66
}
注意:我们在下面通过指针修改常量时,很可能会失效
int main()
{
const int a = 10;
int *p = (int*)&a;
*p = 20;
cout<<a<<endl; //a打印的值依旧是10
}
解释:原因是编译器优化导致的,遇见a时编译器直接从寄存器中读取10给a,而不从内存中读取
我们可以在定义a时再加一个volatile
修饰,避免编译器优化
int main()
{
volatile const int a = 10;
int *p = (int*)&a;
*p = 20;
cout<<a<<endl; //a打印出的是20
}
回到右值引用,由于我们可能需要改变右值引用的值:
int main()
{
int && b = 66;
b++;
cout<<b<<endl;
}
所以右值引用的声明方式:
Type && 右值引用名 = 右值表达式;