Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The meaning of static in C++

I thought I was fairly good with C++, it turns out that I'm not. A previous question I asked: C++ const lvalue references had the following code in one of the answers:


#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; }

The above code outputs X: 100, X:200. I do not understand why. I played with it a bit, and added some more output, namely, a cout before the delete x; and a cout after the new x; within the reset control block.

What I got was: before delete: 0x92ee018 after new: 0x92ee018

So, I figured that static was silently failing the update to x, and the second getX was playing with (after the delete) uninitialized memory; To test this, I added a x = 0; after the delete, before the new, and another cout to ensure that x was indeed reset to 0. It was.

So, what is going on here? How come the new returns the exact same block of memory that the previous delete supposedly free'd? Is this just because that's what the OS's memory manager decided to do, or is there something special about static that I'm missing?

Thank you!

like image 932
please delete me Avatar asked Dec 22 '22 21:12

please delete me


2 Answers

That's just what the memory manager decided to do. If you think about it, it makes a lot of sense: You just freed an int, then you ask for an int again... why shouldn't the memory manager give you back the int you just freed?

More technically, what is probably happening when you delete is that the memory manager is appending the memory block you freed to the beginning of the free list. Then when you call new, the memory manager goes scanning through its free list and finds a suitably sized block at the very first entry.

For more information about dynamic memory allocation, see "Inside storage allocation".

like image 72
Martin B Avatar answered Dec 24 '22 12:12

Martin B


To your first question:

X: 100, X:200. I do not understand why.

Since Y.my_x is just a reference to the static *x in GenX, this is exactly how it supposed it to be - both are referencing to the same address in memory, and when you change the content of *x, you get a side effect.

like image 25
Doc Brown Avatar answered Dec 24 '22 12:12

Doc Brown