C++引用分析实例与案例刨析及使用场景分析详解

简介: 多情况使用场景demo1地址和值都不可以修改 只读不可修改,防止误操作demo2指针常量,地址可变,值不可变 用于在函数体内给函数体外的变量更换别名,且别名只在函数体内有效demo3常量指针,地址不变,值可以变 正常的值传递,可以简化指针值传递的繁琐操作


引用

引用的基本使用

作用:给变量起别名

语法:数据类型 &别名 = 原名

示例:

intmain() {

   inta=10;

   int&b=a;

   cout<<"a = "<<a<<endl;

   cout<<"b = "<<b<<endl;

   b=100;

   cout<<"a = "<<a<<endl;

   cout<<"b = "<<b<<endl;

   system("pause");

   return0;

}

网络异常,图片无法展示
|

引用注意事项

  • 引用必须初始化
  • 引用在初始化后,不可以改变

示例:

intmain() {

   inta=10;

   intb=20;

   //int &c; //错误,引用必须初始化

   int&c=a; //一旦初始化后,就不可以更改

   c=b; //这是赋值操作,不是更改引用

   cout<<"a = "<<a<<endl;

   cout<<"b = "<<b<<endl;

   cout<<"c = "<<c<<endl;

   system("pause");

   return0;

}

引用做函数参数

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

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

示例:

//1. 值传递

voidmySwap01(inta, intb) {

   inttemp=a;

   a=b;

   b=temp;

}

//2. 地址传递

voidmySwap02(int*a, int*b) {

   inttemp=*a;

   *a=*b;

   *b=temp;

}

//3. 引用传递

voidmySwap03(int&a, int&b) {

   inttemp=a;

   a=b;

   b=temp;

}

intmain() {

   inta=10;

   intb=20;

   mySwap01(a, b);

   cout<<"a:"<<a<<" b:"<<b<<endl;

   mySwap02(&a, &b);

   cout<<"a:"<<a<<" b:"<<b<<endl;

   mySwap03(a, b);

   cout<<"a:"<<a<<" b:"<<b<<endl;

   system("pause");

   return0;

}

总结:通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单

PS:值传递与地址传递的回顾:

值传递

  • 所谓值传递,就是函数调用时实参将数值传入给形参
  • 值传递时,==如果形参发生,并不会影响实参==

示例:

voidswap(intnum1, intnum2)

{

   cout<<"交换前:"<<endl;

   cout<<"num1 = "<<num1<<endl;

   cout<<"num2 = "<<num2<<endl;

   inttemp=num1;

   num1=num2;

   num2=temp;

   cout<<"交换后:"<<endl;

   cout<<"num1 = "<<num1<<endl;

   cout<<"num2 = "<<num2<<endl;

   //return ; 当函数声明时候,不需要返回值,可以不写return

}

intmain() {

   inta=10;

   intb=20;

   swap(a, b);

   cout<<"mian中的 a = "<<a<<endl;

   cout<<"mian中的 b = "<<b<<endl;

   system("pause");

   return0;

}

总结: 值传递时,形参是修饰不了实参的

地址传递

作用:利用指针作函数参数,可以修改实参的值

示例:

//值传递

voidswap1(inta ,intb)

{

   inttemp=a;

   a=b;

   b=temp;

}

//地址传递

voidswap2(int*p1, int*p2)

{

   inttemp=*p1;

   *p1=*p2;

   *p2=temp;

}

intmain() {

   inta=10;

   intb=20;

   swap1(a, b); // 值传递不会改变实参

   swap2(&a, &b); //地址传递会改变实参

   cout<<"a = "<<a<<endl;

   cout<<"b = "<<b<<endl;

   system("pause");

   return0;

}

总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递

引用传递

可以修饰实参。本质:接收(int *const a ,int * const b) 传入(&a,&b),编译器自动把识别引用所以使用引用时只传入(a,b)即可。

网络异常,图片无法展示
|

注意:别名可以和原名相同

引用做函数返回值

分析

作用:引用是可以作为函数的返回值存在的

注意:不要返回局部变量引用

用法:函数调用作为左值

示例

//返回局部变量引用

int&test01() {

   inta=10; //局部变量

   returna;

}

//返回静态变量引用

int&test02() {

   staticinta=20;

   returna;

}

intmain() {

   //不能返回局部变量的引用

   int&ref=test01();

   cout<<"ref = "<<ref<<endl;//第一次结果正确,编译器做了保留

   cout<<"ref = "<<ref<<endl;//第二次可能会输出乱码

   //如果函数做左值,那么必须返回引用

   int&ref2=test02();

   cout<<"ref2 = "<<ref2<<endl;

   cout<<"ref2 = "<<ref2<<endl;

   test02() =1000;

   cout<<"ref2 = "<<ref2<<endl;

   cout<<"ref2 = "<<ref2<<endl;

   system("pause");

   return0;

}

解析:返回值类型后面加上and符int&相当于用引用的方式返回数据。如下图例子返回的是a的一个别名,再用一个别名ref去接收函数返回的别名,最终ref是a的一个别名。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

上图结果:第二次输出就是乱码了,编译器不再保留改函数栈区数据a的地址!

网络异常,图片无法展示
|

但是加上static关键字后数据性质就不一样了,静态变量存贮与静态区,程序运行后释放!

网络异常,图片无法展示
|

可以作为左值就是可以进行和变量一样的操作,编译器不会报错。

PS:上图案例刨析

案例分析:函数返回值不能返回局部变量的引用 类比于 不能返回局部变量的地址

旧知识回顾:不能返回局部变量的地址

栈区:

由编译器自动分配释放, 存放函数的参数值,局部变量等

注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

示例:

int*func()

{

   inta=10;

   return&a;

}

intmain() {

   int*p=func();

   cout<<*p<<endl;//第一次编译器可能会保留

   cout<<*p<<endl;//第二次直接会报错!取决于编译器。

   system("pause");

   return0;

}

引用的本质

分析

本质:引用的本质在c++内部实现是一个指针常量(指针指向不可改).

讲解示例:

//发现是引用,转换为 int* const ref = &a;

voidfunc(int&ref){

   ref=100; // ref是引用,转换为*ref = 100

}

intmain(){

   inta=10;

   

   //自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改

   int&ref=a;

   ref=20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;

   

   cout<<"a:"<<a<<endl;

   cout<<"ref:"<<ref<<endl;

   

   func(a);

   return0;

}

结论:C++推荐用引用技术,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了

图析

网络异常,图片无法展示
|

int * const ref = &a;指针常量,地址不可以改变,值可以改变,即引用的地址不可以改变,即引用不可更改

旧知回顾

引用注意事项

  • 引用必须初始化
  • 引用在初始化后,不可以改变

常量引用

作用:常量引用主要用来修饰形参,防止误操作

在函数形参列表中,可以加==const修饰形参==,防止形参改变实参

示例:

//引用使用的场景,通常用来修饰形参

void showValue(const int& v) {

//v += 10;

cout << v << endl;

}


int main() {


//int& ref = 10;  引用本身需要一个合法的内存空间,因此这行错误

//加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;

const int& ref = 10;


//ref = 100;  //加入const后不可以修改变量

cout << ref << endl;


//函数中利用常量引用防止误操作修改实参

int a = 10;

showValue(a);


system("pause");


return 0;

}

加入const表示只读不可修改,防止误操作

实例刨析

网络异常,图片无法展示
|

既然引用的实质是指针,那我们可以利用指针的性质来进行一些实验性操作,见上图的demo1-demo3

多情况使用场景

demo1地址和值都不可以修改

只读不可修改,防止误操作

demo2指针常量,地址可变,值不可变

用于在函数体内给函数体外的变量更换别名,且别名只在函数体内有效

demo3常量指针,地址不变,值可以变

正常的值传递,可以简化指针值传递的繁琐操作

目录
相关文章
|
18天前
|
存储 C++ 容器
C++STL(标准模板库)处理学习应用案例
【4月更文挑战第8天】使用C++ STL,通过`std:vector`存储整数数组 `{5, 3, 1, 4, 2}`,然后利用`std::sort`进行排序,输出排序后序列:`std:vector<int> numbers; numbers = {5, 3, 1, 4, 2}; std:sort(numbers.begin(), numbers.end()); for (int number : numbers) { std::cout << number << " "; }`
19 2
|
1月前
|
存储 安全 C++
在C++指针和引用
在C++指针和引用
|
1月前
|
存储 JSON 安全
【C++ JSON库 json值的创建手段】深入探究C++中JSON对象定位与操作:从引用到回调函数
【C++ JSON库 json值的创建手段】深入探究C++中JSON对象定位与操作:从引用到回调函数
66 0
|
1月前
|
算法 安全 大数据
【C/C++ 随机函数行为】深入探索C++中的随机数:std::random_device与rand的行为分析(二)
【C/C++ 随机函数行为】深入探索C++中的随机数:std::random_device与rand的行为分析
48 0
|
1月前
|
设计模式 算法 数据安全/隐私保护
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用(二)
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用
25 0
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用(二)
|
1月前
|
存储 算法 编译器
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用(一)
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用
41 0
|
18天前
|
程序员 C++
C++语言模板学习应用案例
C++模板实现通用代码,以适应多种数据类型。示例展示了一个计算两数之和的模板函数`add&lt;T&gt;`,可处理整数和浮点数。在`main`函数中,展示了对`add`模板的调用,分别计算整数和浮点数的和,输出结果。
12 2
|
30天前
|
并行计算 算法 安全
【C++ 迭代器 】C++ 迭代器标签的使用场景
【C++ 迭代器 】C++ 迭代器标签的使用场景
41 0
|
30天前
|
设计模式 安全 C++
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
71 2
|
30天前
|
监控 安全 算法
悬垂引用与临时对象在C++中的深入探讨: 风险、原因与预防策略
悬垂引用与临时对象在C++中的深入探讨: 风险、原因与预防策略
54 3