函数不能返回局部指针变量

声明自动指针变量时,编译器为其在堆栈区分配内存,如果在函数中将另外一个自动变量的地址赋值给自动指针变量,在函数调用完毕后,指向堆栈区的栈顶指针将移动到调用此函数之前的地址位置,从而使自动变量失去意义,返回的失去意义的地址将会使程序不稳定。


函数返回指针。本来就是一个比较容易出问题的操作。在霍顿的《VC++ 入门经典》一书中,给出了一个很有代表性的例子,如下:

// Ex5_11.cpp

#include <iostream>

using std::cout;

using std::endl;

double* treble(double);                   // Function prototype

int main(void)

{

   double num = 5.0;                      // Test value

   double* ptr = 0;                       // Pointer to returned value

   ptr = treble(num);

   cout << endl

        << "Three times num = " << 3.0*num;

   cout << endl

        << "Result = " << *ptr;           // Display 3*num

   cout << endl;

   system("pause");

   return 0;

}

// Function to treble a value - mark 1

double* treble(double da
 
ta)

{

   double result = 0.0;

   result = 3.0*da
 
ta;

   return &result;

}



两个输出语句,一个直接输出3*5=15.另一个在一个函数中进行了乘法运算,也是5*3,存到result变量中也没有任何问题。返回这个变量的指针,输出时再接触引用。貌似也没有错误。两条输出语句似乎都应该输出15.但事实不是这样。编译器会抛出[Warning] address of local variable `result' returned 这样一个警告信息。程序运行后的结果也并非是我们预想的那样。第二条输出语句会输出一个不可预见的值。这是怎么回事呢?

仔细分析一下,result是作用域在treble函数中的局部变量。当函数执行结束后。变量result会被析构。其原先占用的内存区域已经被系统回收,可以存储任何数据。而返回的指向该地址的指针也失去了其原有的意义。因此我们得到这样一条准则:

永远不要从函数中返回局部自动变量的地址。

 

如果你真的需要这样操作。你可以在函数的参数表中传入一个指针变量。然后将需要写入的数据写入到该指针变量指向的地址。由于该指针指向的变量,作用域在函数体之外。因此不会在函数结束结束时被回收。

现在回到我们遇到的问题。时间函数localtime就是一个返回指针的函数。返回值类型:tm*

该如何接收这个返回值?当然是声明一个与之类型相同的变量。

于是你会这样写:tm* result;

接下来呢?还用问?赋值嘛。是不是这样:result=localtime(....);

返回什么类型,当然要给什么类型的变量赋值。但是这样却发生了我们不想看到的结果。

也许你想到了。就是这个指针!返回的指针在函数结束后不再有效。正确的方法可以是:

tm result;

result = *localtime(....);

也可以是:

tm* result;

*result = *localtime(...);

正确的方法的共同特点是在函数结束前,对返回的指针解除引用。然后用这个数值,为变量或指针指向的内存区域赋值。也就是说必须要复制函数的返回值。因为函数体中变量会被析构。

指针是灵活而强大的,避免低级错误,明确基本概念。才能让指针更好的为我们服务


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值