zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    迁移MSSQL实例的所有login(包含密码)
    某公司的存储过程模板(摘抄自高大神的博客)
    检测和终结死锁
    70-461学习笔记,关于几个日期函数
    Oracle-12541:TNS:无监听程序 .
    C#- 实用的Log4Net日志记录例子
    EASYUI- EASYUI左移右移 GRID中值
    MYSQL- 分页存储过程
    MSSQLSERVER数据库- 一条代码搞定单表备份表结构和表数据
    Delphi- 操作EXCEL
  • 原文地址:https://www.cnblogs.com/FLYMANJB/p/13357702.html
Copyright © 2011-2022 走看看