我认为我对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.它是。
那么,这里发生了什么?为什么新的返回完全相同的内存块,以前的删除据说是免费的?这只是因为操作系统的内存管理器决定做什么,或者我缺少哪些关于静态的特殊内容?
谢谢!
答案 0 :(得分:8)
这就是内存管理员决定做的事情。如果你考虑一下,它就会很有意义:你刚刚释放了一个int,然后你又要求一个int ...为什么内存管理器不应该给你刚刚释放的int?
从技术上讲,当你delete
时,内存管理器正在附加你释放到空闲列表开头的内存块,可能会发生什么。然后当你调用new
时,内存管理器会扫描其空闲列表,并在第一个条目中找到一个合适大小的块。
有关动态内存分配的详细信息,请参阅"Inside storage allocation"。
答案 1 :(得分:1)
您正在访问已解除分配的内存块。根据c ++标准,这是一种未定义的行为,因此任何事情都可能发生。
修改强>
我想我必须画画:
<强> EDIT2 强>
答案为什么:实施定义。编译器可以在任何喜欢的位置创建新对象。
答案 2 :(得分:1)
关于你的第一个问题:
X:100,X:200。我不明白为什么。
由于Y.my_x
只是对static *x
中GenX
的引用,这正是它应该是的样子 - 两者都引用内存中的相同地址,当你改变* x的内容,就会产生副作用。
答案 3 :(得分:1)
我在VC2008中测试你的代码,输出是X:100,X:-17221323。我认为原因是静态x被释放。我认为我的测试是合理的。
答案 4 :(得分:-1)
这对代码非常有意义。
请记住,它是你的指针是静态的,所以当你第二次输入这个函数时你不需要创建一个新的指针,但是当你进入这个函数时,你正在为指针指向一个新的int到。
你也可能处于调试模式,花费更多的时间给你很好的地址。
究竟为什么你的指针所指向的int在同一个空间中可能只是为了纯粹的运气,而且你没有在它之前声明任何其他变量,所以内存中的相同空间仍然是免费的