C11 左值引用与右值引用

有左值与右值就有了左值引用与右值引用

内置类型

右值引用

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;
}

常量左值引用是一个万能引用类型,可以接收左值、右值、常量左值和常量右值。需要注意的是普通的左值引用不能接收右值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秉麟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值