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