C++ 基础(3)引用

1. 概述

引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样

引用的实质是对一个内存空间起别名

例:

	int a = 1;
	// 变量类型 &引用名 = 变量名
	int	&t = a;
	cout << a << endl; // 1
	cout << t << endl; // 1
	t = 10;
	cout << a << endl;  // 10
	cout << t << endl; // 10

注意:

  1. &在这里不是求地址运算,而是起标识作用
  2. 声明引用时,必须同时对引用进行初始化 ,并且无法重新赋值为其他变量
  3. 引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名
  4. 声明一个引用,并不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。所以对引用求地址,就是对目标变量求地址,&t与&a相等
  5. 不能建立数组的引用。因为数组是一个由若干个元素所组成的集合,所以无法建立一个数组的别名

二. 引用的应用

2.1 引用作为函数参数

void increment(int &param) // 使用引用,param是实参的别名,相当于对实参的调用
{
    
    
	param++;
}

int main() 
{
    
    
	int a = 1;
	cout << a << endl; // 1
	increment(a);
	cout << a << endl; // 2
	return 0;
}
  1. 传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应实参的操作
  2. 使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作。如果使用一般变量传递函数的参数,当发生函数调用时,需要给 形参分配存储单元,形参变量是实参变量的副本,如果传递的是对象,还将调用拷贝构造函数。当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好
  3. 使用指针作为函数的参数虽然也能达到与使用引用的效果,但是在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的 形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰

2.2 常引用

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用

	int a = 1;
	//const 数据类型 &引用名 = 变量名;
	const int &t = a;
	t = 2; // 编译不通过
	a = 3; // 编译通过

还是第一个例子的 自增函数:

void increment(const int &param) // const 修饰引用
{
    
    
	param++; // 编译报错
}

2.3 引用作为返回值

用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本

int &increment(int &param)
{
    
    
	param++;
	return param;
}
int main() 
{
    
    
	int a = 1;
	int b = increment(a);
	cout << a << endl;
	cout << b << endl;
	return 0;
}

链式编程:

class Person
{
    
    
public:
	string name;
	int age;
	int account;
	Person &setName(string name)
	{
    
    
		this->name = name;
		return *this;
	}
	Person &setAge(int age)
	{
    
    
		this->age = age;
		return *this;
	}
	Person &setAccount(int account)
	{
    
    
		this->account = account;
		return *this;
	}
};

int main()
{
    
    
	Person p;
	p.setName("海洋")
		.setAge(21)
		.setAccount(-20000);
	cout << "name = " << p.name << ", age = " << p.age << ",account = " << p.account << endl;
	return 0;
}

引用作为返回值,必须遵守以下规则:

  1. 不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了 “无所指” 的引用,程序会进入未知状态
  2. 不能返回函数内部new分配的内存的引用。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak
  3. 可以返回类成员的引用,但最好是const。主要原因是当对象的属性是与某种业务规则相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常 量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。

三. 引用总结

  1. 引用的实质是对一个内存空间起别名
  2. 引用与指针的区别是,指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作
  3. 在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不如意的问题
  4. 用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性

猜你喜欢

转载自blog.csdn.net/haiyanghan/article/details/112792698