C++引用那点事

目录

一、引用的概念

二、引用的基本语法 

三、引用的本质

四、引用作为函数参数

五、引用与返回值

六、引用与结构体

七、 引用与常量


一、引用的概念

引用是C++对C语言的重要扩展。

它的作用是为变量创建一个别名,通过这个别名我们可以直接操作原变量。比如你有一个本名(变量),同时有一个小名或者别称(引用),其他人通过本名或者小名都可以找到你。任何对引用的操作,实际上都是对原变量的操作。

示例:

int val= 1021;
int &p = val;                    //p是val的引用
p=415;                           //修改p的值会影响val
cout << "val=" << val<< endl;    //打印出来的结果是 val=415

二、引用的基本语法 

引用使用&作为标识符

基本格式:

数据类型 &引用名 = 引用的目标;

int a = 10;
int &r = a;  // 定义一个 int 类型的引用 r,引用变量 a

三、引用的本质

引用的本质是 C++ 内部实现的 指针常量。因此,引用与指针有着相似之处,但它是更高层次的抽象,提供了更方便的操作方式。

定义引用时需要注意以下几点:

引用必须初始化:定义引用时,必须为其指定一个初始化目标。

int a = 10;
int &r = a;  // r 必须在定义时初始化

引用的类型与目标类型必须一致:引用的类型必须与它所引用的变量类型保持一致。(继承和多态除外)

int a = 10;
int &r = a;  // 类型一致

引用不可更改目标:一旦引用绑定到一个变量上,不能再更改其引用的目标。
下列程序是正确的,但是并不能说明:引用能重新赋值.很明显,引用是不能重新赋值的,只是理解上错了!
引用的赋值:是指引用初始化时,它的引用对象只能是变量,并且,一旦它指定为某一个对象的引用后,就不能更改了。
但是,可以用这个引用来改变它的对象的值,从而达到引用的目的——作为变量对象的别名。
如下例,引用p初始化为a,即p从此以后一直是a的引用,若想让p不再是a的引用而成为别的变量的引用那是不可能的。
所以,接下来的一句"p=b;"就不能理解成:取消p是a的引用而将p作为b的引用。
正确的理解应该是:利用引用p来改变它所指对象a的值,即相当于语句"p= 2048;"。
若在下示例语句"p = b;"后加上一句"b= 10",
结果将是:"a = 2048;  b = 10; p = 2048",从这个结果就能很好理解了。


int a = 1021;
int b = 2048;
int &p = a;
p = b;
cout << "a=" << a << endl;

四、引用作为函数参数

作用:函数传参时,可以利用引用的技术让形参修饰实参

*优点:可以简化指针修改实参

示例

#include <iostream>
#include <string>

using namespace std;
void fun_swap_1(int val_1, int val_2)
{
	int temp = val_1;
	val_1 = val_2;
	val_2 = temp;
}
void fun_swap_2(int *val_1, int *val_2)
{
	int temp = *val_1;
	*val_1 = *val_2;
	*val_2 = temp;
}
void fun_swap_3(int val_1, int val_2)
{
	int temp = val_1;
	val_1 = val_2;
	val_2 = temp;
}
int main(int argc, char const *argv[])
{
	int val_1 = 415;
	int val_2 = 526;
	// 原始值
	printf("原始值为:val_1=%d,val_2=%d\n", val_1, val_2);  
	// 值传递
	fun_swap_1(val_1, val_2);
	printf("值传递:  val_1=%d,val_2=%d\n", val_1, val_2);//值传递不能交换两个变量的值
	// 指针传
	fun_swap_2(&val_1, &val_2);
	printf("指针传递val_1=%d,val_2=%d\n", val_1, val_2);//指针传递能交换两个变量的值
	// 引用传递
	fun_swap_3(val_1, val_2);
	printf("引用传递val_1=%d,val_2=%d\n", val_1, val_2);//引用传递能交换两个变量的值
	return 0;
}

结果

原始值为:val_1=415,val_2=526
值传递:  val_1=415,val_2=526
指针传递:val_1=526,val_2=415
引用传递:val_1=526,val_2=415

五、引用与返回值

我们平时使用函数时,函数的返回值都是一个右值。

但是引用作为函数的返回值时,返回值是一个左值。

  • 左值:既可以放在等号左边,也可以放在等号右边的值。
  • 右值:只能放在等号右边的值。

引用作为函数的返回值,不能返回局部变量的引用,因为局部变量在函数调用结束时就被回收了。

可以返回全局变量的引用或者 static 修饰的局部变量的引用。

示例1

#include <iostream>
using namespace std;

// 返回静态局部变量的引用
int &my_add(const int &x, const int &y) {
    static int temp = x + y;  // 静态局部变量
    return temp;  // 返回 temp 的引用
}

// 返回全局变量 value 的引用
int value = 100;
int &func() {
    return value;  // 返回 value 的引用
}

int main() {
    // 返回 temp 的引用
    int &r1 = my_add(10, 20);  // r1 绑定到 temp
    cout << r1 << endl;  // 输出 30

    // 返回全局变量 value 的引用
    int &r2 = func();  // r2 绑定到 value
    cout << r2 << endl;  // 输出 100

    // 修改 value 的值
    r2 = 200;
    cout << value << endl;  // 输出 200

    // 通过 func() 修改 value
    func() = 300;
    cout << value << endl;  // 输出 300

    return 0;
}

六、引用与结构体

当结构体中包含引用的成员时,定义结构体的对象时,必须对引用进行初始化。由于引用必须在创建时绑定到某个变量,因此不能延迟初始化。

1、引用结构:

2、结构体内部有引用:

初始化方式

MyStruct T1 = { .valur = 20 , .ref = val };  // 错误的写法,不能使用初始化列表的指定成员
MyStruct T1 = { 20 , val };  // 正确的写法,必须按照结构体成员顺序进行初始化

代码示例

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

struct MyStruct {
	int valur;   // 普通成员
	int &ref;    // 引用成员,必须在初始化时绑定
};

int main() {
	int val = 10;  // 用于初始化引用的变量
	MyStruct T1 = { 20, val };  // 初始化结构体,包括引用成员
	val = 20;  // 修改引用绑定的变量的值
	cout << T1.ref << endl;  // 输出 20,因为引用指向 val
}

七、 引用与常量

当 const 修饰引用时,它被称为常引用。常引用的作用是禁止通过引用来修改其引用的目标变量。

作用:防止对引用目标的错误修改,保护数据的完整性。

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

int func_Add(const int &val_1, const int &val_2) {
    return val_1 + val_2;
}

int main() {
    // 变量
    int val = 10;
    // 引用 常量引用
    cosnt int &ref = val;

// 常量引用 引用变量
    cout << "ref = " << ref << endl;

// 常量引用 作为参数
    int val_1 = 80;
    int val_2 = 80;
    cout << "val_1 + val_2 = " << func_Add(val_1, val_2) << endl;

// 常用引用 引用常量
    // int & ref_1 = 10;  // 不使用常量引用是不能引用常量的
    const int & ref_1 = 10;

    const int val_3 = 50;

    // int & ref_2 = val_3;  // 不使用常量引用是不能引用const 所修饰的常量
    const int & ref_2 = val_3;

// 常量引用 引用临时值
    // int & ref_3 = val_1 + val_2;  // 不使用常量引用是不能引用临时值的
    const int & ref_3 = val_1 + val_2;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值