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

携手创作,一起成长!这是我参与「日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

引证

引证的根本运用

效果: 给变量起别号

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

示例:

int main() {
​
    int a = 10;
    int &b = a;
​
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
​
    b = 100;
​
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
​
    system("pause");
​
    return 0;
}

引证注意事项

  • 引证必须初始化
  • 引证在初始化后,不能够改动

示例:

int main() {
​
    int a = 10;
    int b = 20;
    //int &c; //过错,引证必须初始化
    int &c = a; //一旦初始化后,就不能够更改
    c = b; //这是赋值操作,不是更改引证cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
​
    system("pause");
​
    return 0;
}

引证做函数参数

效果: 函数传参时,能够运用引证的技术让形参润饰实参

长处: 能够简化指针修正实参

示例:

//1. 值传递
void mySwap01(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}
​
//2. 地址传递
void mySwap02(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
​
//3. 引证传递
void mySwap03(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}
​
int main() {
​
    int a = 10;
    int b = 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");
​
    return 0;
}
​

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

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

值传递

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

示例:

void swap(int num1, int num2)
{
    cout << "交流前:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;
​
    int temp = num1;
    num1 = num2;
    num2 = temp;
​
    cout << "交流后:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;
​
    //return ; 当函数声明时分,不需求回来值,能够不写return
}
​
int main() {
​
    int a = 10;
    int b = 20;
​
    swap(a, b);
​
    cout << "mian中的 a = " << a << endl;
    cout << "mian中的 b = " << b << endl;
​
    system("pause");
​
    return 0;
}

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

地址传递

效果: 运用指针作函数参数,能够修正实参的值

示例:

//值传递
void swap1(int a ,int b)
{
    int temp = a;
    a = b; 
    b = temp;
}
//地址传递
void swap2(int * p1, int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
​
int main() {
​
    int a = 10;
    int b = 20;
    swap1(a, b); // 值传递不会改动实参
​
    swap2(&a, &b); //地址传递会改动实参
​
    cout << "a = " << a << endl;
​
    cout << "b = " << b << endl;
​
    system("pause");
​
    return 0;
}

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

引证传递

能够润饰实参。实质:接纳(int *const a ,int * const b) 传入(&a,&b),编译器主动把辨认引证所以运用引证时只传入(a,b)即可。

注意:别号能够和原名相同

引证做函数回来值

剖析

效果:引证是能够作为函数的回来值存在的

注意:不要回来局部变量引证

用法:函数调用作为左值

示例

//回来局部变量引证
int& test01() {
    int a = 10; //局部变量
    return a;
}
​
//回来静态变量引证
int& test02() {
    static int a = 20;
    return a;
}
​
int main() {
​
    //不能回来局部变量的引证
    int& ref = test01();
    cout << "ref = " << ref << endl;//第一次结果正确,编译器做了保存
    cout << "ref = " << ref << endl;//第2次可能会输出乱码//如果函数做左值,那么必须回来引证
    int& ref2 = test02();
    cout << "ref2 = " << ref2 << endl;
    cout << "ref2 = " << ref2 << endl;
​
    test02() = 1000;
​
    cout << "ref2 = " << ref2 << endl;
    cout << "ref2 = " << ref2 << endl;
​
    system("pause");
​
    return 0;
}

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

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

可是加上static要害字后数据性质就不一样了,静态变量存贮与静态区,程序运行后开释!

能够作为左值便是能够进行和变量一样的操作,编译器不会报错。

PS:上图案例刨析

案例剖析:函数回来值不能回来局部变量的引证 类比于 不能回来局部变量的地址

旧知识回忆:不能回来局部变量的地址

栈区:

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

注意事项:不要回来局部变量的地址,栈区拓荒的数据由编译器主动开释

示例:

int * func()
{
    int a = 10;
    return &a;
}
​
int main() {
​
    int *p = func();
​
    cout << *p << endl;//第一次编译器可能会保存
    cout << *p << endl;//第2次直接会报错!取决于编译器。
​
    system("pause");
​
    return 0;
}

引证的实质

剖析

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

讲解示例:

//发现是引证,转换为 int* const ref = &a;
void func(int& ref){
    ref = 100; // ref是引证,转换为*ref = 100
}
int main(){
    int a = 10;
    
    //主动转换为 int* const ref = &a; 指针常量是指针指向不行改,也说明为什么引证不行更改
    int& ref = a; 
    ref = 20; //内部发现ref是引证,主动帮咱们转换为: *ref = 20;
    
    cout << "a:" << a << endl;
    cout << "ref:" << ref << endl;
    
    func(a);
    return 0;
}

结论: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常量指针,地址不变,值能够变

正常的值传递,能够简化指针值传递的繁琐操作