因为这个原因,局部变量经常被分配到栈数据结构里,因为一个栈的特点是第一个入栈的元素将会最后一个出栈。 这就好像酒店决定只能按照顺序进行房间的出租。你没办法离开,除非你之前所有房间号比你大的人都走了。 所以,让我们来想一下栈的操作过程。在很多操作系统中,每一个线程都有一个栈,并且栈的大小是一个可变的确定大小。当你调用一个函数的时候,相关的内容被压 入栈内。当你把一个这个栈的指针传出这个函数时,就像上面的提问者所干的一样。那个指针只是指向全部有效的数百万个字节内存块的中间。在我们的类比中,当 你离开酒店的时候,你只是离开了当前被占用的数字最大的房间。如果没有人在你之后入住,你又非法地回到了这个房间。你所有的东西肯定都还在这个酒店的房间 里。 我们用栈作为临时存储因为它们非常廉价并且容易实现。C++的实现没有规定一定要用栈来存储局部变量,你可以使用堆来存储它们,不过没有人这么干,因为那样做会使得程序变得很慢。 C++也没有规定在你离开栈之后需要清掉栈里的内容,所以你可以在之后非法地回到栈里找到你之前的内容。当然编译器如果生成代码,一旦你不再使用了就把栈里的所有内容都清零,这是完全合法的。不需要再解释为什么了,因为这样做代价非常高。 C++ 没有规定要确保当栈变小时,之前有效的内存地址依然有效。C++的实现也允许告诉操作系统“我们已经不再需要栈的个内存页了。除非我说,否则当有任何人要 访问这个之前有效的栈的内存页的时候抛出一个异常并结束程序”。再次,一般的实现也没有这么做,因为这么说使程序变慢而且没有必要。 相反,大多数时候,一般的C++实现允许你犯错然后避免它。直到有一天,一些真正非常令人恐怖的错误出现了然后把整个程序弄崩溃了。 这样做是有问题的。C++里有如此多的规则而又如此轻易就可以打破它们。我自己就有好多次这样的经历。更糟的是,这种问题往往是表面的,当你发现内存地址冲突了之后去检查内存,却发现它们在很长时间内又是正确的。所以你很难知道到底是哪个地方出错了。 那些内存安全的语言通过限制你的能力来解决这个问题。在规范的C#里,没有任何办法去获取一个局部变量的内存地址,然后返回它或者是存储它等以后再用。你可 以获取一个局部变量的内存地址,但是语言被很好的设计了,你不可能在局部变量生命周期之后还能够使用它。为了取得局部变量的内存地址并把它返回,你必须要 把编译器设置为一个特殊的不安全的模式,并且在你的程序里写上“unsafe”关键字。这可以帮助提醒你,你正在做一些不安全的可能会打破规则的事情。 更进一步阅读: http://blogs.msdn.com/b/ericlippert/archive/2011/06/23/ref-returns-and-ref-locals.aspx 为什么我们用栈来管理内存?C#里值的类型是否一直存储在栈里?虚拟内存是如何工作的?以及更多的关于C#内存管理是如何工作的。这里许多文章都对C++程序员有帮助。 http://blogs.msdn.com/b/ericlippert/archive/tags/memory+management/ 原文链接: StackOverflow 翻译: 伯乐在线 - 菜鸟浮出水 |