Andrei Moiseev
Andrei Moiseev

Reputation: 4084

Basic question about C++ memory management

// main.cpp

class Cat()
{
public:
     Cat()
     {
          a = 0;
          (*b) = 0;
     }

     int a;
     int* b;
};

int main(int argc, char* argv[])
{
     Cat cat1;
     Cat* cat2 = new Cat();
     return 0;
}

Usially I don't care about memory, but I want to understand clearly, in what memory do cat1's and cat2's a and b exist? In stack or in heap?

@BoPerson: You're right, I should have used b = new int(0). But it's more interesting for me, where is variable a when object Cat is created in heap? a in heap, too? And pointer b in heap too and it points to memory in heap, right?

Upvotes: 1

Views: 433

Answers (3)

Tilman Vogel
Tilman Vogel

Reputation: 9773

Let me annotate and answer in-place.

class Cat()
{
public:
     Cat()
     {
          a = 0; // ok: sets the variable a, wherever it lives
          (*b) = 0; // not ok: stores an integer 0 to wherever b points
                    // since b was never initialized to anything, it can write
                    // anywhere you can imagine. If you are lucky, your compiler
                    // implicitly initializes the pointer to zero such that you
                    // at least get a deterministic segmentation violation.
     }

     int a; // an integer variable living wherever Cat gets constructed
     int* b; // a pointer variable living wherever Cat gets constructed pointing 
             // to wherever it gets set to (b = something) could be heap, stack, 
             // mapped memory, out-of-control (like here)
};

int main(int argc, char* argv[])
{
     Cat cat1; // allocates cat1 on the stack, all attributes (a and b) live 
               // there. Where cat1.b points to is unrestricted.
     Cat* cat2 = new Cat(); // allocates an object of class Cat on heap, 
               // allocates a pointer variable cat2 on the stack and stores the 
               // pointer to said heap-allocated Cat in it
               // again, where cat2.b points to is unrestricted.
     return 0; // maybe never reached due to segfault ;-)
}

As you refer to memory management in your title: Stack variables get destructed automatically when they fall out of scope. I.e. the space occupied by cat1 and cat2 (one Cat, one pointer) will be recovered when leaving main(). Also, for cat1, the destructor will be called. In your case, there is no explicit destructor but if Cat had attributes with destructors, an automatic destructor would get auto-generated.

For pointers, the object pointed to is not automatically destructed when the pointer gets destructed. If you want that, you should have a look at smart pointers like std::auto_ptr<> (or QScopedPoiner in Qt) which gives you a pointer-like object which will indeed destruct the pointed-to object (by calling delete on it) when the auto_ptr gets destructed.

When not employing smart pointers, you need to take care to manually destruct the pointed-to-objects using the delete operator. Take care to do it on every return-path from your current scope (multiple returns, thrown exceptions, e.g.).

Upvotes: 8

user227466
user227466

Reputation:

The new keyword allocates your object to the heap. While your first example allocated memory to the stack.

Cat cat1; //stack

Cat* cat2 = new Cat(); //heap

Stack memory is not as readily available as heap memory. Basically, you store memory on the heap with the new and store that address in a pointer.

Memory on the heap can also be deleted. Using the 'delete' command. Which makes your program run more efficiently.

Am I missing any key pointers anyone?

EDIT: memory on the heap should be deleted when no longer in use, not just for efficency, but to avoid the program inflate. (Memory Leaks) - Thanks @Felice Pollano

Upvotes: 4

Goz
Goz

Reputation: 62323

cat1 is allocated on the stack. The class is 8 bytes (if ints and pointers are 4 bytes on your platform). The first 4 bytes is the integer a. The second 4 bytes is the integer b.

cat2 is allocated in heap memory. Otherwise its exactly the same as above.

Stack variables are "scoped". This means that when the stack frame is popped (ie exiting the function) it is free'd and its deconstructor is called.

Heap variables on the other hand will hang around until you "delete" the memory.

Also note that your constructed is malformed. "*b" dereferences the pointer (ie gets at the data the pointer is pointing too). You then assign 0. The problem that arises is that b does not point at any determined memory so you are writing 0 to an unknown memory location which may not be in your processes address space. I would have thought you really mean "b = NULL;"

Upvotes: 1

Related Questions