• C++中如何在函数中返回局部变量的指针/引用/地址?


    01 不能直接返回局部变量的引用/地址

    C++有时候还挺傻的,比如调用函数的时候,我就想返回一个局部变量的引用或指针(常想用于返回新建的数组/对象),是不正确的。

    比如下面这段代码,用指针存储变量 \(a\) 的地址并返回(直接返回 \(a\) 的地址的话,在编译器那关就过不了):

    // 程序
    #include <iostream>
    using namespace std;
    
    int *get10(){
        int a = 10;
        int *b = &a;
        return b;
    }
    
    int main() {
        int *c10 = get10();
        cout << *c10 << endl;
        return 0;
    }
    
    // 结果
    10
    

    结果似乎是正确的,但是如果我们增加一个函数,真个代码是这样的:

    // 程序
    #include <iostream>
    using namespace std;
    
    int *get10(){
        int a = 10;
        int *b = &a;
        return b;
    }
    
    int *get20(){
        int a = 20;
        int *b = &a;
        return b;
    }
    
    int main() {
        int *c10 = get10();
        int *c20 = get20();
        cout << *c10 << endl;
        cout << *c20 << endl;
        return 0;
    }
    
    // 结果
    20
    22024
    

    可以看出,这个结果是随机的,我们不能返回局部变量的指针/引用,这些局部变量包括:

    • 指针
    • 引用
    • 数组
    • 类对象
    • 函数

    这些对象的底层存储都是利用指针来实现的,比如说数组,在计算机中实际是用指针存储的是数组第一个元素的地址。

    之所以不能返回局部变量的指针/引用/地址的原因如下:

    局部变量:在函数内部定义的变量称为局部变量,局部变量存储在函数栈区,当程序调用结束后,在函数栈区的所有东西将会由计算机进行销毁。

    全局变量:函数外面的变量称为全局变量,它随着程序运行的结束自动进行销毁。

    我们在函数内声明的局部变量,想要返回,返回值分为两种情况:

    • 针对int、float这类简单对象,拷贝一份,进行返回(返回前后变量的地址是不一样的);
    • 针对涉及到指针这类更为复杂的对象,不做任何处理;

    就好像拆迁,两种情况:

    • 你家小的,得了,重新安置一个地方给你。
    • 你家大几千亩,也没那么多地方安置你,给你小的你也住不下,那就不赔了,但拆还是要拆的。

    所以,我们不应该返回局部变量的指针或者引用。而第一个程序能得到正确结果原因在于,C++的内存清理机制是惰性的,要等到下一位住客住进来,它才会进行内存的清理,因而在程序中,我们可以得到10的结果。

    02 如何返回复杂的局部变量

    这里说的复杂,是指用到指针的,主要有三种处理方法:

    • 函数内new出来,函数外用完delete(反人类,不安全);
    • static 改为静态的(随着整个程序结束才销毁,浪费空间)
    • 作为全局变量,将地址传入函数(推荐)

    这里只说第三种方法(Python之禅,对于某个效果,有且只有一个实现):

    • 函数外定义全局变量
    • 将变量引用传入函数
    • 函数内完成修改
    // 程序
    #include <iostream>
    using namespace std;
    
    void add_x_to_Array(int array[], int x, int n){
        for (int i = 0; i < n; ++i) {
            array[i] = array[i] + x;
        }
    }
    
    int main() {
        int array[2] = {0, 1};
        add_x_to_Array(array, 10, 2);
        for (int i = 0; i < 2; ++i) {
            cout << array[i] << endl;
        }
        return 0;
    }
    
    10
    11
    

    完成修改,对于指针这类数据,也是一样的。

    飞翔的荷兰人 邮箱:fly_cjb@163.com
  • 相关阅读:
    SVN如何切换用户对代码进行操作
    SVN更新的时候报断言失败解决办法
    根据身份证号判断性别
    4.UiCollection API 详细介绍
    1.UiDevice API 详细介绍
    安卓常见反破解方式
    腾讯应用加固的脱壳分析和修复
    1.Android JUnit Runner(使用AndroidStudio)
    Java图形化界面设计——布局管理器之null布局(空布局)
    Java图形化界面设计——布局管理器之CardLayout(卡片布局)
  • 原文地址:https://www.cnblogs.com/FLYMANJB/p/13357702.html
Copyright © 2020-2023  润新知