C ++中static的含义

时间:2010-11-11 08:37:32

标签: c++ memory-management static

我认为我对C ++相当不错,事实证明我不是。我问过上一个问题:C++ const lvalue references在其中一个答案中包含以下代码:


#include <iostream>
using namespace std;

int& GenX(bool reset) { static int* x = new int; *x = 100; if (reset) { delete x; x = new int; *x = 200; } return *x; }

class YStore { public: YStore(int& x); int& getX() { return my_x; } private: int& my_x; };

YStore::YStore(int& x) : my_x(x) { }

int main() { YStore Y(GenX(false)); cout << "X: " << Y.getX() << endl; GenX(true); // side-effect in Y cout << "X: " << Y.getX() << endl; return 0; }

以上代码输出X:100,X:200。我不懂为什么。 我玩了一下,并添加了一些输出,即删除x之前的cout;和新的x之后的cout;在复位控制块内。

我得到的是: 删除前:0x92ee018 新的:0x92ee018

所以,我认为静态无声地更新到x,第二个getX正在播放(删除后)未初始化的内存;为了测试这个,我添加了一个x = 0;在删除之后,在新的之前,以及另一个cout确保x确实被重置为0.它是。

那么,这里发生了什么?为什么新的返回完全相同的内存块,以前的删除据说是免费的?这只是因为操作系统的内存管理器决定做什么,或者我缺少哪些关于静态的特殊内容?

谢谢!

5 个答案:

答案 0 :(得分:8)

这就是内存管理员决定做的事情。如果你考虑一下,它就会很有意义:你刚刚释放了一个int,然后你又要求一个int ...为什么内存管理器不应该给你刚刚释放的int?

从技术上讲,当你delete时,内存管理器正在附加你释放到空闲列表开头的内存块,可能会发生什么。然后当你调用new时,内存管理器会扫描其空闲列表,并在第一个条目中找到一个合适大小的块。

有关动态内存分配的详细信息,请参阅"Inside storage allocation"

答案 1 :(得分:1)

您正在访问已解除分配的内存块。根据c ++标准,这是一种未定义的行为,因此任何事情都可能发生。

修改

我想我必须画画:

  1. 您为int分配内存,并将堆上分配的对象传递给Y的构造函数,该构造函数将其存储在引用中
  2. 然后您释放该内存,但您的对象Y仍保留对已释放对象的引用
  3. 然后再次访问Y对象,该对象包含无效引用,引用已释放的对象,并且您获得的结果是未定义行为的结果。
  4. <强> EDIT2

    答案为什么:实施定义。编译器可以在任何喜欢的位置创建新对象。

答案 2 :(得分:1)

关于你的第一个问题:

  

X:100,X:200。我不明白为什么。

由于Y.my_x只是对static *xGenX的引用,这正是它应该是的样子 - 两者都引用内存中的相同地址,当你改变* x的内容,就会产生副作用。

答案 3 :(得分:1)

我在VC2008中测试你的代码,输出是X:100,X:-17221323。我认为原因是静态x被释放。我认为我的测试是合理的。

答案 4 :(得分:-1)

这对代码非常有意义。

请记住,它是你的指针是静态的,所以当你第二次输入这个函数时你不需要创建一个新的指针,但是当你进入这个函数时,你正在为指针指向一个新的int到。

你也可能处于调试模式,花费更多的时间给你很好的地址。

究竟为什么你的指针所指向的int在同一个空间中可能只是为了纯粹的运气,而且你没有在它之前声明任何其他变量,所以内存中的相同空间仍然是免费的