指针类型_的_函数返回值(指针函数)

  无情的搬砖机器= =

一、函数返回值的要点

注意(原则):可以返回局部变量本身,但永远不要返回一个局部变量的指针或引用(其实是隐式的指针)

原因:局部变量只是临时的存储空间,因为函数执行完之后,将释放分配给局部变量的存储空间,此时,对局部变量的引用和地址就会返回不确定的内存(野指针)。

系统堆栈的知识点

  函数调用过程中,一个函数在调用另外一个函数的时候,会先将调用前的现场信息保存在系统堆栈中,然后按照从又向左的顺序(c语言)将实参的结果入栈,而被调用的函数的形参,用的就是实参的空间,当被调用的函数运行结束后,局部变量的空间被“释放”的本质,其实是栈顶的指针,移动到了调用前函数的现场信息的地方,所以刚才被调用的函数的局部变量,实际上它的值还是存放在内存中,并且在当前栈顶指针的上面的连续空间中。

简单理解

  函数执行完,局部变量会被释放,此时指向 已释放的局部变量 的指针 是很危险(不确定)的;如果不调用还好(但不调用,那要返回值干嘛?);

  一旦其他函数调用该函数返回值指针,该指针指向的内存不确定就会造成不可知的错误。

二、举例

  1. 返回变量本身

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //这个返回变量本身内存可以,正确
    int add(int x, int y)
    {
    int sum = x + y;
    return sum;
    }

    int main()
    {
    int a = 3, b = 5;
    cout << add(a, b) << endl;
    }
  2. 返回局部变量指针,用法错误

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int* add(int x, int y)
    {
    int sum = x + y;
    return &sum;
    }

    int main()
    {
    int a = 3, b = 5;
    cout << *add(a, b) << endl;
    }

会出现以下警告:

warning: function returns address of local variable [-Wreturn-local-addr] return &sum;

警告:函数返回地址是局部变量地址—>这是不安全的

三、解决方案和利弊

3.1 解决方案

该如何解决这种错误呢?有以下3种常用方案:

  1. 使用静态变量
  2. 使用全局变量
  3. 申请堆区变量

其实,使用这三种方法都是为了延长变量的声明周期,从而达到返回的地址是确定的而不是不确定的。

法1:

1
2
3
4
5
6
7
8
9
10
11
int* add(int x, int y)
{
static int sum;
sum = x + y;
return &sum;
}
int main()
{
int a = 3, b = 5;
cout << *add(a, b) << endl;
}

法2:

1
2
3
4
5
6
7
8
9
10
11
12
13
int sum;

int& add(int x, int y)

{
sum = x + y;
return sum;
}
int main()
{
int a = 3, b = 5;
cout << *add(a, b) << endl;
}

法3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int* add(int x,int y)
{
int* sum = new int;
*sum = a + b;
return sum;
}
int main()
{
int a = 3, b = 5;
int *result;
result = add(a, b);
cout << *result << endl;
delete result;
}

  但法3需要注意,由于用new申请的动态内存,调用者(这里是main)需要释放这个申请的指针free, delete

3.2 利弊

  1. 法3的 申请堆区变量 比较麻烦,一般不常用;
  2. 法2的 使用全局变量 比较鸡肋;如果是全局变量的(函数返回值)指针,为啥不直接调用该指针,函数就不需要返回(全局)指针,该返回值充其量像是 提示 ,或者是函数格式要求
  3. 法1的 使用局部变量 比较推荐

总结:指针类型的函数返回值 还是不推荐用。

  采用return语句返回的指针,原本想法是让函数返回多个数值(数组、结构体);但指针往往是作为函数形参来直接改变实参(数值),从而让函数变相返回多个数值;因此,指针类型的函数返回值,功能少且鸡肋(容易出事),不推荐使用

-------------本文结束感谢您的阅读-------------