关于C++中的局部变量

       以前在面试软件工程师的时候,面试官经常会问关于c++中不同变量生成和释放的过程,即内存和堆栈管理。当时花了很多时间死记了一些这方面的知识,也不太明白为什么面试官会对这个问题这么重视。后来在真正参与软件研发后才深刻理解这个问题的重要性。

      这里不一一介绍所有变量的存放位置和生命周期,只说几讲在最近开发过程中遇到的关开局部变量的问题。
 

看如下的代码:

CTicTacToc::CTicTacToc()
{
    CBoardAI iBoardAI(m_nPieceColor);
    m_piBoardAI= &iBoardAI;
}

  在构造函数中生成的一个类的对象,并将这个对象的地址传入到成员变量m_piBoardAI中。然后在其后用m_piBoardAI访问 iBoardAI的成员函数。
  这是一个典型的buger,这是因为在构造函数中生成了一个临时变量,在构造函数退出后这个成员变量会被释放掉。是的,m_piBoardAI是不会被释放,但是它指向的内容已经被释放了,所以一访问就会崩!

        针对这个问题,后来又研究了一下其它关于返回临时变量的问题。在这里把一些自己觉得有意义的东西整理下来。

//test1.c
#include <stdio.h>
char* get_str()
{
    char str[] = {"hello"};
    return str;
}

int main()
{
    char* p = get_str();
    printf("%s/n", p);
    return 0;
}
/*test2.c*/

#include <stdio.h>
char* get_str()
{
    char *str = {"hello"};
    return str;
}

int main()
{
    char* p = get_str();
    printf("%s/n", p);
    return 0;
}
 

运行结果:test2.c运行是没有问题的,也可以打印出正确的值,而test1.c却是错误的,打印出来的值和预期的完全不一样。

问题:他们都是返回了局部变量的指针,为什么会有差异呢?

原因:我们仔细看代码,发现他们只有一个地方不一样,那就是test1.c 里面str是一个数组,test2.c里面str是一个指针,原因就在这。在test2.c中str指针,其值是一个常量,而常量是放在数据段里面的,即便函数返回了,数据段里面的常量数据也还会在,直到程序结束才会消失,所以我们可以打印出来。而对于test1.c中的数组来说,它是一个局部变量,是放在栈里面的,函数返回之后,str指向的空间还是在的,如果我们打印出该数组的地址会发现地址是没有变的。那么为什么数组的内容(地址指向的内容)会变掉呢?难道是系统会把栈中的数据清除,答案是否定的,操作系统没必要这么做,下次用到这块内存还是会进行初始化的,这样做会消耗系统的资源。之所以在test1.c中打印出来数组的内容会变掉是因为printf本身是个函数,在函数调用时会进行参数的压栈,在压栈的过程中会把原来str指向的空间覆盖掉,因些也就改变了str指向的空间的值。如果我们在 get_str之后,不调用任何函数并不创建新的局部变量(严格的说是不使栈继续往下增长),这个时候str指向的内容还是没变的。

结论:指向常量的临时变量指针可以返回,这是因为这种临时变量是放在数据段里的,直到程序结束后才释放!

再来看一个返回局部变量的例子:

int test()

{

  int a; 
  a = 5; 
  return a; 

}

int b=test();
 

尽管a被销毁了,但它的副本5还是成功地返回了,这样做没有问题。

在返回局部实体的时候,如果用数据去接收 如 int b=test();

这时候会隐含的做一次拷,把test返回来的(5)复制到b中;

这里之所以成功是因为函数返回来是值,面不是a。。。(这是我个人的理解,是不是正确,以后再去确认)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值