c++引用

1.什么是c++引用?

引用是c++对c的重要扩充。c++中新增了引用的概念,引用可以作为一个已定义变量的别名。

#include "stdafx.h"
#include <iostream>
using namespace std;
// 1.引用的基本使用
void test01(){
	int a = 10;
	// 给变量a取一个别名为b
	int &b = a;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << "----------" << endl;
	// 操作b就相当于操作a本身
	b = 100;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << "----------" << endl;
	// 一个变量可以有n个别名
	int &c = a;
	c = 200;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << "c:" << c << endl;
	cout << "-----------" << endl;
	// a,b,c的地址都是相同的
	cout << "a:" << &a << endl;
	cout << "b:" << &b << endl;
	cout << "c:" << &c << endl;
}
// 2.使用引用注意事项
void test01(){
	// (1)引用必须初始化
	// int &ref; // 报错:必须初始化引用
	// (2)引用一旦初始化,不能改变引用
	int a = 10;
	int b = 20;
	int &ref = a;
	// ref = b; // 不能改变引用
}
int main(){
	test01();
	return 0;
}

建立数组的引用

#include "stdafx.h"
#include <iostream>
using namespace std;

int main(){
	// 1.建立数组引用方法一
	typedef int ArrRef[10];
	int arr[10];
	ArrRef& aRef = arr; // 给数组arr取别名为ArrRef
	for (int i = 0; i < 10;i++){
		aRef[i] = i + 2;
	}
	for (int i = 0; i < 10;i++){
		cout << arr[i] << " ";
	}
	cout << endl;
	// ★2.建立数组引用方法二
	int(&f)[10] = arr;
	for (int i = 0; i < 10;i++){
		f[i] = f[i] + 10;
	}
	for (int i = 0; i < 10;i++){
		cout << arr[i] << " ";
	}
	cout << endl;
	// ★ &arr == &aRef == &f
 	return 0;
}

2.引用的本质

引用的本质是在c++内部实现一个常指针。

Type& ref = val; // Type* const ref = &val;

c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,只是这个过程是编译器内部实现,用户不可见。

#include "stdafx.h"
#include <iostream>
using namespace std;

// 发现是引用,转换为 int* const ref = &a;
void testFunc(int& ref){
	ref = 100; // ref是引用,转换为*ref = 100
}

int main(){
	int a = 10;
	int& aRef = a; //自动转换为int* const aRef = &a; 这也能说明引用为什么必须初始化
	aRef = 20; // 内部发现aRef是引用,自动帮我们转换为:*Ref=20;
	cout << "a:" << a << endl;
	cout << "aRef:" << aRef << endl;
	testFunc(a);
 	return 0;
}

3.指针的引用(重难点)

下面就是p1就是翠花的变量别名。cout<<p1得到结果就是翠花。

给指针变量取别名,就是指针的引用。我们可以把下面指针引用进行类比,就好理解了:

char* p = "翠花" // 等价于 int a = 10
char* &p1 = p // 等价于int &b=p

// 这就相当于引用的基本用法呗。

指针的引用,代码如下所示:

#include "stdafx.h"
#include <iostream>
using namespace std;

void test01(){
	char* p = "翠花";
	char* &p1 = p;
	cout << p1 << endl;
}

int main(){
	test01();
	system("pause");
 	return 0;
}

一个字节对应的是8位,而malloc(size)中的size是以字节为单位。

#include <iostream>
using namespace std;

// 被调函数
void func(char* *tmp){
	char *p;
	p = (char*)malloc(64); // 64个字节大小
	memset(p, 0, 64); // 清空p的内存,64个长度
	strcpy(p, "小花"); // 拼接字符串
	*tmp = p; // 一级指针*tmp装的是变量*p的地址p。
}

// 主调函数
void test01(){
	char* mp = NULL;
	func(&mp); // 二级指针装的是一级指针变量的地址。这个可以看【c一级指针二级指针那篇文章】
	cout << mp << endl;
}

int main(){
	test01();
	system("pause");
	return 0;
}

使用指针变量引用方法:

#include <iostream>
using namespace std;

// 被调函数
void func(char* &tmp){ // ★等价于 char* &tmp = mp,这叫给指针变量mp取别名为tmp。
	char* p;
	// 那p到底是变量值还是地址?变量值
	p = (char*)malloc(64); // 64个字节大小
	memset(p, 0, 64); // 清空p的内存,64个长度
	strcpy(p, "小花你好"); // 拼接字符串
	tmp = p; // 省略了*
}

// 主调函数
void test01(){
	char* mp = NULL;
	func(mp); // 省略了&
	cout << mp << endl;
}

int main(){
	test01();
	system("pause");
	return 0;
}

4.引用的使用场景

第一种:引用作为参数

#include <iostream>
using namespace std;

// 被调函数
void func(int &a, int &b){ // int &a=a相当于给变量a取别名为a。
	int sum = a + b;
	cout << "sum=" << sum << endl;
}

// 主调函数
void test01(){
	int a = 10;
	int b = 20;
	func(a, b);
}

int main(){
	test01();
	system("pause");
	return 0;
}

第二种:引用作为函数的返回值

#include <iostream>
using namespace std;

int &func2(){ // 声明这个函数的返回值是个引用,那么接收也要是引用变量。
	int b = 10;
	int &p = b;
	return p;
}

void test01(){
	int &q = func2();
	cout << q << endl;
	//  可以通过变名改变值
	q = 100;
	cout << q << endl;
	// 也可以通过函数返回值改变值
	func2() = 200;
	cout << q << endl;
}

int main(){
	test01();
	system("pause");
	return 0;
}

5.常量引用和普通引用区别

#include <iostream>
using namespace std;

int main(){
	// 普通引用
	int a = 10;
	int &ref = a;
	ref = 20;
	
	// int &ret2 = 10; // 不能给字面量取别名 err
	const int &ref3 = 10; // 可以给const修饰的引用赋予字面量
	// const修饰符修饰的引用的原理
	// 编译器会把上面的代码变为: int tmp = 10; const int &ref3 = tmp;
	system("pause");
	return 0;
}

6.函数的默认参数和占位参数

#include <iostream>
using namespace std;

int myFunc(int a, int b = 0){
	return a + b;
}

void test01(){
	// 函数的默认参数的作用
	// 当函数内常要用到形参的某个值,但偶尔要使用其他值
	// 增加函数的灵活性
	cout << myFunc(10, 20) << endl;
	cout << myFunc(10) << endl;
}

int main(){
	test01();
	system("pause");
	return 0;
}

两个注意点:

//注意点:
//1. 形参b设置默认参数值,那么后面位置的形参c也需要设置默认参数
void TestFunc02(int a,int b = 10,int c = 10){}
//2. 如果函数声明和函数定义分开,函数声明设置了默认参数,函数定义不能再设置默认参数
void TestFunc03(int a = 0,int b = 0);
void TestFunc03(int a, int b){};

比如下面的例子是错误的:

#include <iostream>
using namespace std;

void TestFunc03(int a, int b= 0);
void TestFunc03(int a, int b = 1){ // 因为声明时候已经设置了默认参数b=0,了,那么定义时候就不能再设置默认参数b=1了。
	cout << a + b << endl;
}

int main(){
	TestFunc03(1, 2);
	system("pause");
	return 0;
}

7。函数传递参数的三种方式

#include <iostream>
using namespace std;

// 值传递
void swap1(int a, int b){
	int temp = a;
	a = b;
	b = temp;
}

// 指针传递
void swap2(int *a, int *b){
	int temp = *a;
	*a = *b;
	*b = temp;
}

// 引用传递
void swap3(int &a, int &b){
	int temp = a;
	a = b;
	b = temp;
}

//打印
void myprint(int &a, int &b){
	cout << "a=" << a <<" "<< "b=" << b << endl;
}

int main(){
	int a = 10;
	int b = 20;
	cout << "初始值:" << a << " " << b<<endl;
	swap1(a, b); // 注意点swap(a,b)是内部方法
	myprint(a,b); // 10 , 20。因为形参的a和实参的a不是同一个
	swap2(&a, &b); // 
	myprint(a, b); // 20 , 10。
	swap3(a, b); // 
	myprint(a, b); // 又被转回来了:10 , 20。
	system("pause");
	return 0;
}

值传递:

指针传递:

引用传递(别名):

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值