Stack vs. Heap (C++)

Started by
26 comments, last by alvaro 14 years, 10 months ago
Heya all, It's been awhile since I've posted here. I just started a new job where creating variables stack and heap, depending on their use, is an absolute must. I'm always getting yelled at for the wrong one. I've asked around the office and the consensus is that if I don't know this then I must not be up for the job, but honestly no one has explained this concept to me before. Consider:

class Foo 
{
   Foo(Bar _b);
   Bar bar;
   int counter;
};

Foo::Foo(Bar _b):  // Creates a stack or heap?
Bar(_b)
{
// stuff
}



A simple answer will do. If someone can point me to a good article, or in fact articulate the difference to me, I will forever send you Jelly Belly's.
~Argonaut________________________________Why "~Argonaut"? It's all just a mathematical expression denoting a close approximation of "Argonaut", which is irrational and can't be precisely defined.
Advertisement
Stack
Heap

In your example, it is stack.

int* ptr = new int;

is heap.
Declaring a local variable or a function parameter puts it on the stack.
Declaring a pointer and then pointing it at an object created with new puts it on the heap.

edit: drat, beaten
OK, thanks. Perhaps I'm kinda dumb, but I know what stack and heap memory spaces are. What I was wondering about was the C++ syntax. Specifically, with the : after the class constructor. Does that create the object on the stack or the heap?

(I know enough of ASM to know how stacks and heaps work, but my prof in my compiler class was a dickhead who only talked about his cats)

Answering this question would go along way to easing my pain:

Perhaps I'm not asking this question correctly. What is the difference between:

Foo::Foo(Bar _b) :Bar(_b){}


and

Foo::Foo(Bar _b){  bar = _b;}

?
~Argonaut________________________________Why "~Argonaut"? It's all just a mathematical expression denoting a close approximation of "Argonaut", which is irrational and can't be precisely defined.
If _b is passed by value (which you seem to be doing), the value of _b will be on the stack.

The member variable bar should be a part of the class, so I assume it gets created wherever the class is in memory.

I could be wrong, but I'm assuming the member initializer there would just invoke a copy constructor and copy the value of _b into bar.

I therefore assume that bar would be created wherever the rest of the class is. Depending on how you instantiate the object, that would be either on the stack or on the heap. So it could be either.

edit: To answer your last question, I don't think there is much of a difference. I could however be wrong.
Thank you for your answer Oberon, but apparently there is a difference, since I keep getting yelled at for it.

However, there could be something fundamentally wrong with my understanding of what is going on here.
~Argonaut________________________________Why "~Argonaut"? It's all just a mathematical expression denoting a close approximation of "Argonaut", which is irrational and can't be precisely defined.
Foo::Foo(Bar _b){  bar = _b;}

everything is on the stack (unless Foo itself is on the heap).
bar is first default constructed, then operator = assigns to it.

Foo::Foo(Bar _b) :Bar(_b){}

Again, everything is on the stack (unless Foo itself is on the heap).
bar is copy constructed.

This means that the second example can be significantly faster for objects with non-trivial default constructors.

Also
Foo::Foo(const Bar &_b) :Bar(_b){}

could be even better, since this line:
Foo x( Bar() );

In the first example causes: Bar to construct, Bar to be copied, Foo::Bar to default construct, Foo::Bar to be assigned to.

In the third example you only get: Bar constructed, refrence of Bar passed to Foo(), Foo::Bar initalized by copy constructor.

OK, wait ...

Should I be doing as such:

Foo::Foo(Bar& _b) :Bar(_b){}


to keep the var on the stack and:

Foo::Foo(Bar _b){   bar = _b;}


to move it (at least implicitly) to the heap?
~Argonaut________________________________Why "~Argonaut"? It's all just a mathematical expression denoting a close approximation of "Argonaut", which is irrational and can't be precisely defined.
KulSeran wins. Thanks so much!!!
~Argonaut________________________________Why "~Argonaut"? It's all just a mathematical expression denoting a close approximation of "Argonaut", which is irrational and can't be precisely defined.
The difference between using an initializer list or not has nothing to do with whether objects live on the stack or on the heap.

About your original question:
* If you have a local variable of type Foo, you created the object on the stack (by the way, you don't say that you "created a stack").
* If you use `new Foo(my_bar)', you are creating an object on the heap.
* And if you have a global variable of type Foo, you are creating an object that is neither in the stack nor the heap.

The difference between a constructor for Foo that uses an initializer list to initialize bar versus a constructor for Foo that assigns to bar is that in the first case, bar is constructed directly with the constructor you specify, while in the second case, bar is first constructed using a default constructor and then it is assigned to. Often this will make very little difference, but some classes don't have default constructors and in some other cases default-constructing an object and assigning to it is less efficient than constructing it with the right constructor.

You are also asking about the difference between passing an argument by reference versus passing it by value. If you pass by value, you can expect the compiler might make a copy of the object being passed. If you pass by reference (or by pointer), effectively only the address is passed around. If the only reason you are passing a reference is to avoid a copy, you should pass a const reference. Otherwise you are indicating that the function might change something in the object being passed. Again, this has nothing to do with whether the stack or the heap are being used.

Now, if you have questions about any of the three issues above (stack-vs-heap, initializer lists and passing by value or by reference), try to not mix them up in your question.

This topic is closed to new replies.

Advertisement