Jotin2
Jotin2

Reputation: 39

What is the difference between declaring a variable directly and using the keyword new?

When you declare directly the variable occupy a chunk of data, but when you declare a variable with the keyword new it initializes a pointer with memory from the "free store" which is basically unused memory. What is the difference between these?

int *p_int = new int;
int *p_int;

Upvotes: 1

Views: 683

Answers (4)

John Bupit
John Bupit

Reputation: 10618

int *p_int = new int; creates a pointer *p_int, and points it to a newly allocated space from the heap (the free store).

int *p_int; just creates a pointer *p_int, but does not point it to any specific memory location - it points to an undermined location.

When you do something like *p_int = 42;, it will set the value of that allocated block to 42, in the first case. The second case, since it isn't pointing to somewhere specific, may produce erroneous results.

Upvotes: 0

zar
zar

Reputation: 12227

int *p_int = new int;

These are two things. A pointer variable and the actual object. Think of this as a glass with water.

int *p_int;

This is just one variable and there is no actual object. Think of this as glass without any water.

int my_int

This is another case which is also just one item but in this case it is the water and no glass.

Upvotes: 0

tenfour
tenfour

Reputation: 36896

There are a lot of differences.

Dynamic Allocation

int *x = new int;

This is known as "dynamic allocation".

new int allocates memory on the heap to store an int, and returns the address of this memory (a pointer). So after this statement, x will be a memory address, like 0x200fd2a11 or whatever. The memory it points to can be used as an integer. Here is the same example, a bit expanded:

int *x;// declare a pointer to an integer. at this stage, x is uninitialized and does not point to anything.
x = new int;// set x to point to a newly allocated int.
*x = 4;// now we are using the integer for the first time, setting it to 4.
delete x;// you must delete dynamically allocated memory, or you'll have a memory leak.

Notice that you're dealing with two different values here: a pointer, and the integer.

Also notice that you must delete the pointer when you're done with it, to free up that memory.

Auto Allocation

OK let's move on and describe how that differs from:

int x;
x = 4;

Here, x is an "auto variable". The biggest fundamental difference is that its storage is allocated on the stack. Here is a sort of list of differences between dynamic and auto allocation:

  • Auto variables will be cleaned up automatically when they leave scope. This means you don't need to bother using delete, but it means you don't have as fine of control over its lifetime.
  • Stack memory is a fixed size. So if you try to do int x[100000000]; your app will likely crash.
  • Auto variables don't deal with the pointer indirection. You have direct access to the value without having to dereference a pointer (the asterisk in like *x = 4;). You can just do x = 4;.
  • Auto variables' size must be known at compile-time, because of how code is generated to deal with the stack. For this reason, you can't do things like int x[y];, because the amount to allocate is not known at compile-time.

When do I use dynamic v. auto?

Auto is simpler and at least as fast as dynamic, so default to auto. UNLESS:

  1. The size is not known at compile time
  2. or, the size is "big". Like, bigger than a few hundred bytes and I usually move to the heap. It helps debugging and is safer.
  3. or, the lifetime is not bound to a scope in your code. For example if you need an object to be allocated in a function, and continue living after that function returns.

In practice

But finally, in modern C++ we try to avoid pointers. Having to manually delete memory is annoying and error-prone. No matter how diligent you are, it's a recipe for memory leaks. For dynamic arrays, use std::vector. For allocating objects that need to be shared around by many things, use smart pointer objects (unique_ptr, shared_ptr, weak_ptr). There is almost always a safer option than to use raw pointers.

Upvotes: 6

jbruni
jbruni

Reputation: 1247

A variable declared in a block is allocated (usually) within the stack frame of the function. It's lifespan is limited to that of the function or block which contains it. When you exit the function, the memory on the stack is released. For recursive functions, each function block will have its own, independent version of the variable.

When a variable is allocated using "new", the memory for the object is allocated on the free store. It's lifespan is until the memory is released using "delete". These types of allocations must be tracked because they are not automatically reclaimed. These are useful for objects which must live past the lifetime of the allocating function.

The biggest difference, then, is lifespan and ownership.

When you allocate something via new:

int* p_int = new int{42};

You are actually allocating two objects, a block of memory the size of an int, initialized to the value 42, and a pointer-to-int, initialized to the address of the memory block. You must track the lifespan of the memory block and release it using delete. The memory of "p_int" itself (not what it points to) is on the stack and will be released when you exit.

Upvotes: 0

Related Questions