有左值与右值就有了左值引用与右值引用
内置类型
右值引用
int main () { int x=10; int &a=x;//左值引用 const int &b=x;//常量左值引用,全能型值类别引用 int &&rc=x;//右值引用,不能引用左值 int &&rd=20;//右值引用,可以引用纯右值 const int &e=10;//常量左值引用,它是全能型值类别引用 return 0; }
具名右值引用自身为左值
int main () { int &&a=10; int &&b=a;//error int &c=a;//ok const int&d=a;//ok }
总结:右值引用a是具名右值引用,编译器会将已命名的右值引用视为左值。
右值引用与函数重载
//左值引用 void func(int &val) { cout<<"L value reference"<<endl; } //常量左值引用 void func(const int &val) { cout<<"const L value reference"<<endl; } //右值引用 void func(int &&val) { cout<<"r value reference"<<endl; } int main() { int a=10; const int b=20; func(a); func(b); func(10); return 0; }
func(a):优先联编func(int &val),如果没有,其次联编func(const int&val);不能与func(int &&val)联编。
func(b):首先联编func(const int&val),不能与func(int &val)和func(int &&val)联编。
func(10) :优先联编func(int&&val),如果没有,其次联编func(const int &val);不能与func(int &val)联编。
函数返回值
int func() { int x=10; return x; } int main () { int a=func(); int &b=func();//error;func返回的是一个将亡值(右值) const int &c=func(); int &&d=func(); return 0; } int func() { int x=10; cout<<"&x: "<<&x<<endl; return x; } int main () { int a=func(); int &b=func();//error const int &c=func(); int &&d=func(); cout<<"&d: "<<&d<<endl; return 0; }
总结:func()函数返回的数值是将亡值,不能以左值引用接收
左值引用与函数返回值
int &func() { int x=10; return x; } int main () { int a=func(); int &b=func(); const int&c=func(); int &&d=func();//无法将右值引用绑定到左值 return 0; }
函数返回值是右值引用
int&& func() { return int(10); } int main() { int a = func(); //int& b = func();无法将右值绑定在左值上 const int& c = func(); int&& d = func(); return 0; }
类类型的右值引用
类类型是程序员自己设计的类型
不具名对象
class Int { private: int _value; public: Int(int x = 0) :_value(x) { cout << "Create Int:" << _value << endl; } Int(const Int& it) :_value(it._value) { cout << "Copy Create Int:" << this << endl; } Int& operator =(const Int& it) { if (this == &it) { return *this; } _value = it._value; cout << this << "=" << &it << endl; return *this; } ~Int() { cout << "Destroy Int:" << _value << endl; } void SetValue(int x) { _value = x; } int GetValue()const { cout << "value:" << _value << endl; } void Showvalue()const { cout << "value:" << _value << endl; } }; int main() { Int a = Int(1); //Int& b = Int(2);左值引用的初始值必须为左值 const Int& c = Int(3); Int&& d = Int(4); a.Showvalue(); c.Showvalue(); d.Showvalue(); }
无论声明左值还是右值引用都必you须立即进行初始化,因为引用类型本身并不具有所绑定对象的内存,只是该对象的一个别名。通过右值引用的声明,该右值又重获新生,其生命周期与右值引用类型名的生命周期一样。只要该右值引用名还活着,该右值临时量将会一直存活下去。
构造函数的隐式转换
int main() { const Int& a = 1; Int&& b = 2; //Int&& c = b; b是一个右值引用但b可取地址是左值,左值不可用于右值引用的初始化 Int& dr = b; return 0; } //解释 int main() { const Int& a = 1; //const int &a=(Int)(1); Int&& b = 2; //Int &&b=(Int)(2); //Int&& c = b;err Int& dr = b; return 0; }
使用explicit明确关键,阻止构造函数的隐式转换
class Int { int _value; public: explicit Int(int x = 0) :_value(x) { cout << "Create Int" << _value << endl; } };
右值引用与函数重载
void func(Int& x) { cout << "L value reference" << endl; } void func(const Int& x) { cout << "const L value reference" << endl; } void func(Int&& x) { cout << "r value reference" << endl; } int main() { Int a(1); const Int b(2); func(a); func(b); func(Int(3)); return 0; }
类类型作为函数的返回值
class Int { private: int _value; public: Int(int x = 0) :_value(x) { cout << "Create Int:" << _value << endl; } Int(const Int& it) :_value(it._value) { cout << "Copy Create Int:" << this << endl; } Int& operator =(const Int& it) { if (this == &it) { return *this; } _value = it._value; cout << this << "=" << &it << endl; return *this; } ~Int() { cout << "Destroy Int:" << _value << endl; } void SetValue(int x) { _value = x; } int GetValue()const { cout << "value:" << _value << endl; } void Showvalue()const { cout << "value:" << _value << endl; } }; Int func(int x) { Int tmp(x); return tmp; } int main() { Int a = func(1); Int x(0); x = func(2); //Int& b = func(3);func()函数的返回值是一个将亡值是右值不能使用左值引用 const Int& c = func(4); Int&& d = func(5); a.Showvalue(); c.Showvalue(); d.Showvalue(); x.Showvalue(); return 0; }
可以以值得形式接收对象,也可以const引用接收对象,还可以右值引用接收对象。
通过右值引用,比之前少了一次拷贝构造和一次析构,原因在于右值引用绑定了右值,让临时右值的生命周期延长了。
左值引用作为函数的返回值。
class Int { private: int _value; public: Int(int x = 0) :_value(x) { cout << "Create Int:" << _value << endl; } Int(const Int& it) :_value(it._value) { cout << "Copy Create Int:" << this << endl; } Int& operator =(const Int& it) { if (this == &it) { return *this; } _value = it._value; cout << this << "=" << &it << endl; return *this; } ~Int() { cout << "Destroy Int:" << _value << endl; } void SetValue(int x) { _value = x; } int GetValue()const { cout << "value:" << _value << endl; } void Showvalue()const { cout << "value:" << _value << endl; } }; Int& func(int x) { Int tmp(x); return tmp; } int main() { Int a = func(1); Int x(0); x = func(2); Int& b = func(3); const Int& c = func(4); //Int&& d = func(5);func函数的返回值是一个左值,左值不可以初始化右值引用 a.Showvalue(); c.Showvalue(); b.Showvalue(); //d.Showvalue(); x.Showvalue(); return 0; }
右值引用作为函数的返回值
Int&& func(int x) { Int tmp(x); return tmp;//err } int main() { Int a = func(1); Int x(0); x = func(2); //Int& b = func(3);//func()函数的返回值是一个将亡值是右值不能使用左值引用 const Int& c = func(4); Int&& d = func(5);//func函数的返回值是一个左值,左值不可以初始化右值引用 a.Showvalue(); c.Showvalue(); //b.Showvalue(); d.Showvalue(); x.Showvalue(); return 0; }
常量左值引用是一个万能引用类型,可以接收左值、右值、常量左值和常量右值。需要注意的是普通的左值引用不能接收右值。
C11 左值引用与右值引用
最新推荐文章于 2024-08-27 21:33:46 发布