C++引用与const的结合用法

引用与const的结合用法

引用的基本概念:
(1)引用其实就是给变量其一个别名
(2)其语法形式:变量类型 &别名=原名 例:int &b=a
(3)引用必须进行初始化,int&b是不对的
(4)引用一旦初始化之后就不可更改了
(5)引用的传递:传递有值传递和地址传递。引用传递就是地址传递,通过引用参数产生的效果同按照地址传递是一样的
(6)不要反悔局部变量的引用。函数的调用可以作为左值(如果函数的返回值是引用,这个函数调用可以作为左值)
(7)引用的本质:在C++内部实现是一个指针常量
例:int &a=b;自动转换为int const a=&b,指针常量到的指向不可更改,这也说明了为什么引用不可更改。b=20;内部发现a是引用,自动回帮我们转化为a=20;

int main()
{
	int a = 10, b = 20;
	//int &d1 = a;
	//a = 20;
	//&d11 = b;//因为引用不可改变,b1已经引用a,不可再引用b
	const int& d1 = a;
	a = 100;
	printf("%d %d", a, d11);
	const int d3 = 1;
	const int& d4 = d3;//const常量也必须用常引用
	const int& d5 = 8;//常量具有常属性,只有常引用可以引用常量
	return 0;
}

引用与指针的结合用法

先看一段小代码:

int *&pref=p;//
int &*pref=p;//

解释:
一般这种解释是从右向左解释的
(1)p是一个指针,给它定义了一个别名pref,什么类型的引用呢?是int *类型(整形类型指针)的引用。正确
(2)p是一个指针,定义了一个指针prev指向引用,引用本身是没有空间的。错误

int a=10,b=20;
int *p1=&a;
const int *p2=&a;
int *const p3=&a;
const int *const p4=&a;

通过上边分析下边对错:
注意一个细节:别名的改变会引起指针的改变

int *&pref=p1;//对
int *&pref=p2;//错
//因为*p2是被限制的,而*pref的改变,会引起*p2的改变  改正:const int *&pref=p2;
int *&pref=p3;//错
//因为p2是被限制的,而pref的改变会引起p2的改变  改正:int *const &pref=p3;
int *&pref=p4;//错
//这里*p2和p2都被限制了,所以必须同时限制*pref和pref  改正:const int*const & pref = p4;

const与函数返回值的结合使用

注意:在函数后边加const其实约束的还是this指针,下边两种写法是等价的

    //const Int*GetValue(cosnt Int *const this )
	const Int* GetValue()const
	{
		return &value;
	}
	
#include<iostream>
using namespace std;

class Int
{
private:
	int val;
public:
	Int(int x = 0) :val(x) { cout << "Create Int: " << this << endl; }
	~Int() { cout << "Destroy Int: " << this << endl; }
	Int(const Int& x) :val(x.val)//拷贝构造
	{
		cout << "Copy Create Int: " << this << endl;
	}
	Int(Int&& x)//移动拷贝
	{
		val = x.val;
		cout << "Move Copy Create Int: " << this << endl;
	}

	Int& operator=(const Int& x)//赋值函数
	{
		if (this != &x)
		{
			val = x.val;
		}
		cout << this << " <= " << &x << endl;
		return *this;
	}
	Int& operator=(Int&& x)//移动赋值函数
	{
		if (this != &x)
		{
			val = x.val;
		}
		cout << this << " Move = " << &x << endl;
		return *this;
	}
	//c11


	Int* operator&() { return this; }
	const Int* operator&() const { return this; }

	int& Value() { return val; }
	const int& Value() const { return val; }
};

//下面对四种返回值与const的结合运用进行分析

class Test
{
private:
	Int value;
public:
	Test(int x = 0) :value(x) {}
	~Test() {}
	
	Int GetValue()//以值的形式返回,构建临时对象
	{
		return value;
	}
	
	Int &GetValue()
	{
	    return value;
	}
	
    const Int &GetValue() const//const约束的是this指针,指针的常性传递是向能力缩小的方向传递的 。
	{
	    return value;
	}
	
	Int*GetValue()const
	{
	    return &value;
	}
	const Int* GetValue()const
	{
		return &value;
	}
};
//主函数一:
int main()
{
	Test ta(10);
	Int a1 = ta.GetValue();//对
	Int& a2 = ta.GetValue();//错
	//临时量不可引用
	const Int& a3 = ta.GetValue();//对
	//这里会直接绕过对临时对象的构建,直接构建新对象a3
	Int* p1 = &ta.GetValue();//对
	//构建一个临时对象,用p1去指向这个对象的地址,但这个对象的生存期仅仅限于这条语句
	const Int* p2 = &ta.GetValue();//对
	return 0;
}

执行结果:
在这里插入图片描述

//主函数二:
{
	Test ta(10);
	Int a1 = ta.GetValue();

	Int& a2 = ta.GetValue();
	const Int& a3 = ta.GetValue();

	Int&& a4 = ta.GetValue();//错
	const Int&& a5 = ta.GetValue();//错
	//右值引用引用的必须是纯右值或者将亡值(将亡值指的是以值的形式返回的中间过度者)

	Int* p1 = &ta.GetValue();
	const Int* p2 = &ta.GetValue();
	Int* const p3 = &ta.GetValue();
	const Int* const p4 = &ta.GetValue();
	return 0;
}

注意:引用的本质就是指针,返回引用其实就是返回地址,当编译器发现返回值是以值的形式接受时,就会以这个地址所指的值作为参数调动构造函数去构造一个新对象;对于引用来说,它只是这个返回值的一个别名,并没有构造新对象,指针也一样,指针只是指向这个地址。并不会通过它去构造新对象。
执行结果:
在这里插入图片描述

//既然是以常引用返回,那就必须以常引用来接收
//主函数三:
{
	Test ta(10);
	Int a1 = ta.GetValue();

	Int& a2 = ta.GetValue();//错
	const Int& a3 = ta.GetValue();

	Int* p1 = &ta.GetValue();//错
	const Int* p2 = &ta.GetValue();
	Int* const p3 = &ta.GetValue();//错
	const Int* const p4 = &ta.GetValue();
	return 0;
}

执行结果:
在这里插入图片描述
主函数四:

int main() 
{
	Test ta(10);
	Int a1 = *ta.GetValue();
	cout << endl;
	Int& a2 = *ta.GetValue();
	const Int& a3 = *ta.GetValue();

	//Int*&& a4 = ta.GetValue();
	//const Int&& a5 = ta.GetValue();
	Int* p1 = ta.GetValue();
	const Int* p2 = ta.GetValue();
	Int* const p3 = ta.GetValue();
	const Int* const p4 = ta.GetValue();
}

在这里插入图片描述

主函数五:
加const之后全对

int main() 
{
	Test ta(10);
	cout << endl;
	Int a1 = *ta.GetValue();
	cout << endl;
	Int& a2 = *ta.GetValue();//错
	cout << endl;
	const Int& a3 = *ta.GetValue();
	cout << endl;
	Int*&& b1 = ta.GetValue();//错int*类型的字面常量
	Int* p1 = ta.GetValue();//错
	const Int* p2 = ta.GetValue();
	Int* const p3 = ta.GetValue();//错
	const Int* const p4 = ta.GetValue();
}

附加模板:

template<class Type,size_t N>
void Printf(Type(&br)[N])
{
    for(Type &x:br)
    {
        printf("%d \n",x);
    }
}
引用:int ar[10]
      int (&br)[10]=ar; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值