【C++基础之三】函数中局部变量的返回

2024-08-22 16:32

本文主要是介绍【C++基础之三】函数中局部变量的返回,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引用出处


一般说来,函数中是可以进行局部变量的返回的,不然岂不是全部要用全局变量,如果使用了全局变量,那还有必要进行返回吗?那函数就没有它存在的意义了!但是要注意了,这里所谓的局部变量的返回很有内涵,什么样的值才可以进行返回而不出错?


      其实,只要遵守一句话即可:函数不能返回指向栈内存的指针!


      为什么?因为返回的都是值拷贝

      我们知道,局部变量的作用域是函数内部,函数一旦执行结束,栈上的局部变量会进行销毁,内存得到释放。因此,此时函数返回的是该局部变量的值拷贝,这是没有问题的。但是如果返回的是局部变量的地址,那么返回的只是该局部变量指针的拷贝,而随着函数运行结束,该拷贝指针所指向的栈内存已经被释放,那么指向一个未知区域就会导致调用的错误。


      那如果返回的指针指向的是堆内存,又会怎么样?

      这样的使用是没有问题的,在函数内new空间,在函数外delete空间。但是这样并不是一种好的编程风格,尽量在同一个作用域内进行new和delete操作,否则还要调用者手动进行内存的释放,试问这样的接口是不是很烂。如果确实需要这样做,那就传指针进去吧!


      好吧,通过几个典型的例子看一下,返回局部变量要注意的地方。

      1.正确。最normal的情况。

[cpp]  view plain copy
  1. int returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<returnValue();  
  6.     return 0;  
  7. }  
  8.   
  9. char returnValue()  
  10. {  
  11.     int value=3;  
  12.     return value;  
  13. }  

      2.错误。最normal错误。虽然value被释放,但是它的值不一定会被清除,所以有时候你这么用看起来结果好像也是对的,但是隐患无穷。

[cpp]  view plain copy
  1. int* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<*(returnValue());  
  6.     return 0;  
  7. }  
  8.   
  9. int* returnValue()  
  10. {  
  11.     int value=3;  
  12.     return &value;  
  13. }  

      3.正确。不用奇怪,“HelloJacky”是一个字符串常量,储存在只读数据段,return str只是返回了该字符串在只读数据段所在的首地址,当函数退出后,该字符串所在的内存不会被回收,所以是正常的。

[cpp]  view plain copy
  1. char* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<returnValue();  
  6.     return 0;  
  7. }  
  8.   
  9. char* returnValue()  
  10. {  
  11.     char* str="HelloJacky";  
  12.     return str;  
  13. }  

     4.错误。这一回“HelloJacky”是栈内的局部变量,函数退出时内存被释放,因此返回栈内局部变量的地址是错误的。

[cpp]  view plain copy
  1. char* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<returnValue();  
  6.     return 0;  
  7. }  
  8.   
  9. char* returnValue()  
  10. {  
  11.     char str[]="HelloJacky";  
  12.     return str;  
  13. }  

      5.正确。如果你非要返回一个局部变量的地址,那么加上static吧。

[cpp]  view plain copy
  1. char* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<returnValue();  
  6.     return 0;  
  7. }  
  8.   
  9. char* returnValue()  
  10. {  
  11.     static char str[]="HelloJacky";  
  12.     return str;  
  13. }  
       6.错误,一样的,数组也不能作为函数的返回值,因为数组名其实是局部变量的首地址。

[cpp]  view plain copy
  1. int* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<*(returnValue());  
  6.     return 0;  
  7. }  
  8.   
  9. int* returnValue()  
  10. {  
  11.     int value[3]={1,2,3};  
  12.     return value;  
  13. }  
       7.正确。加上static修饰符吧,那数组也可以返回了。

[cpp]  view plain copy
  1. int* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<*(returnValue());  
  6.     return 0;  
  7. }  
  8.   
  9. int* returnValue()  
  10. {  
  11.     static int value[3]={1,2,3};  
  12.     return value;  
  13. }  

     8.正确。函数内申请空间,调用后释放空间,只是这样做的坏处就如上面所说接口不灵活。

[cpp]  view plain copy
  1. char* newMemory(int size);  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     char* p=newMemory(2);  
  6.     if(p!=NULL)  
  7.     {  
  8.         *p='a';  
  9.     }  
  10.     std::cout<<*p;  
  11.     delete [] p;  
  12.     return 0;  
  13. }  
  14.   
  15. char* newMemory(int size)  
  16. {  
  17.     char* p=NULL;  
  18.     p=new char[size];  
  19.     return p;  
  20. }  

这篇关于【C++基础之三】函数中局部变量的返回的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1096801

相关文章

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

postgresql使用UUID函数的方法

《postgresql使用UUID函数的方法》本文给大家介绍postgresql使用UUID函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录PostgreSQL有两种生成uuid的方法。可以先通过sql查看是否已安装扩展函数,和可以安装的扩展函数

MySQL字符串常用函数详解

《MySQL字符串常用函数详解》本文给大家介绍MySQL字符串常用函数,本文结合实例代码给大家介绍的非常详细,对大家学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql字符串常用函数一、获取二、大小写转换三、拼接四、截取五、比较、反转、替换六、去空白、填充MySQL字符串常用函数一、

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

MySql基本查询之表的增删查改+聚合函数案例详解

《MySql基本查询之表的增删查改+聚合函数案例详解》本文详解SQL的CURD操作INSERT用于数据插入(单行/多行及冲突处理),SELECT实现数据检索(列选择、条件过滤、排序分页),UPDATE... 目录一、Create1.1 单行数据 + 全列插入1.2 多行数据 + 指定列插入1.3 插入否则更

PostgreSQL中rank()窗口函数实用指南与示例

《PostgreSQL中rank()窗口函数实用指南与示例》在数据分析和数据库管理中,经常需要对数据进行排名操作,PostgreSQL提供了强大的窗口函数rank(),可以方便地对结果集中的行进行排名... 目录一、rank()函数简介二、基础示例:部门内员工薪资排名示例数据排名查询三、高级应用示例1. 每