Sign in to follow this  
argonaut

Stack vs. Heap (C++)

Recommended Posts

argonaut    100
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.

Share this post


Link to post
Share on other sites
argonaut    100
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;
}


?

Share this post


Link to post
Share on other sites
Oberon_Command    6082
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.

Share this post


Link to post
Share on other sites
argonaut    100
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.

Share this post


Link to post
Share on other sites
KulSeran    3267

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.

Share this post


Link to post
Share on other sites
argonaut    100
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?

Share this post


Link to post
Share on other sites
alvaro    21247
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.

Share this post


Link to post
Share on other sites
argonaut    100
Quote:
Original post by alvaro

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.


The question was over how initializer lists should be employed. That was all that needed to be said -- "look up something called initializer lists". KulSeran did a nice job of it. I thank you for your help though, and your efforts to make me feel like a dumbass are truly appreciated.

Share this post


Link to post
Share on other sites
alvaro    21247
Quote:
Original post by argonaut
Quote:
Original post by alvaro

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.


The question was over how initializer lists should be employed. That was all that needed to be said -- "look up something called initializer lists". KulSeran did a nice job of it. I thank you for your help though, and your efforts to make me feel like a dumbass are truly appreciated.


That was not the idea at all, and I am sorry if it came through as insulting. Lack of knowledge doesn't make you a dumb ass. I wrote my post hoping that it would help you structure your language and your thoughts about programming.

Share this post


Link to post
Share on other sites
iMalc    2466
None of what you're really asking about has anything to do with stack vs heap. It's ALL on the stack here. The difference between these two is not about where it puts thing.
Foo::Foo(Bar _b) :
bar(_b)
{
}

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

The difference is about unnecessary work being performed (efficiency). The second one first calls the default constructor for bar, and then calls the asignment operator for bar. The assignment operator is reponsible for releasing the current things held by itself, as well as copying the new things to itself.
By using the top one of these two you avoid both the default initialisation, and the undoing of that default initialisaed state, and do only the constructing of the copied state.
(I'm assuming Bar is a class here, and potentially not a tiny class) It's even better to pass _b by reference.
It makes no difference if Bar were say a typedef for int though, but it's still good practice to use constructor initialisation lists every time you actually have a choice. Less code to improve upon if you were to change types later.

Share this post


Link to post
Share on other sites
Decrius    100
If a variable is initialized with 'new' or malloc (or other alloc's) -> heap! And later on destroyed using 'delete' or free -> heap! Anything else -> stack!

Share this post


Link to post
Share on other sites
DevFred    840
Just to clarify, constructors DO NOT create objects. Their job is to initialize objects. How a particular object was created does not concern the constructor.

Share this post


Link to post
Share on other sites
_the_phantom_    11250
Quote:
Original post by Decrius
If a variable is initialized with 'new' or malloc (or other alloc's) -> heap! And later on destroyed using 'delete' or free -> heap! Anything else -> stack!


Unless that variable is a member of a class, in which case it lives wherever the class was constructed.


class Foo
{
Foo(int j) : i(j) {};

int i;
}

Foo * bar = new Foo(42); // i is on the heap

Foo bar(42); // i is on the stack


Note how the use of the initaliser list has no effect on where the member variable is stored.

Share this post


Link to post
Share on other sites
DevFred    840
There is more than stack and heap ;)

Foo x(42); // static storage

int main()
{
Foo y(42); // stack

Foo* z = new Foo(42); // heap
delete z;
}

And isn't the heap actually managed by malloc/free, and new/delete manage the "free store"?

[Edited by - DevFred on June 19, 2009 9:41:26 AM]

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
Original post by argonaut
Specifically, with the : after the class constructor. Does that create the object on the stack or the heap?


That has nothing to do with it.

Google.

You were already shown the syntax for instantiating the class on the heap vs. on the stack. However, you should note that:

1) Member variables of a class all need to appear together; thus, if one is on the heap, they all are.

2) Things dynamically allocated by an object's implementation (e.g. the element storage allocated behind the scenes by std::vector) will always be on the heap, even if the object itself is on the stack, because it's dynamic allocation. (However, the object's data member which points to the dynamic allocation is still in the same place as the rest of the object.)

There's a good chance that none of the people yelling at you know what they're talking about, BTW.

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
Original post by DevFred
Just to clarify, constructors DO NOT create objects. Their job is to initialize objects. How a particular object was created does not concern the constructor.


Roughly speaking, allocate + initialize = create.

Quote:
And isn't the heap actually managed by malloc/free, and new/delete manage the "free store"?


Yes. Most people can't be bothered to distinguish, though. Although they should.

Share this post


Link to post
Share on other sites
rip-off    10976
Quote:

And isn't the heap actually managed by malloc/free, and new/delete manage the "free store"?

Something like that. The only way that is relevant is that you cannot deallocate pointers obtained from operator new using free(), and vice versa.

Share this post


Link to post
Share on other sites
_Sigma    792
Quote:
Original post by Zahlman
Quote:
And isn't the heap actually managed by malloc/free, and new/delete manage the "free store"?


Yes. Most people can't be bothered to distinguish, though. Although they should.

What is the difference again?

Quote:
The question was over how initializer lists should be employed. That was all that needed to be said -- "look up something called initializer lists". KulSeran did a nice job of it. I thank you for your help though, and your efforts to make me feel like a dumbass are truly appreciated.

Given you asked about stack and heap, given you titled your thread about stack and heap, given you kept talking about stack and heap, that is what you got. No need to be snippy, we are just trying to help.

Share this post


Link to post
Share on other sites
_Sigma    792
Quote:
Original post by alvaro
Quote:
Original post by argonaut
Quote:
Original post by alvaro

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.


The question was over how initializer lists should be employed. That was all that needed to be said -- "look up something called initializer lists". KulSeran did a nice job of it. I thank you for your help though, and your efforts to make me feel like a dumbass are truly appreciated.


That was not the idea at all, and I am sorry if it came through as insulting. Lack of knowledge doesn't make you a dumb ass. I wrote my post hoping that it would help you structure your language and your thoughts about programming.

Your reply was polite and informative. I wouldn't worry about it.

Share this post


Link to post
Share on other sites
Bregma    9202
Quote:
Original post by _Sigma
Quote:
Original post by Zahlman
Quote:
And isn't the heap actually managed by malloc/free, and new/delete manage the "free store"?

Yes. Most people can't be bothered to distinguish, though. Although they should.

What is the difference again?


There are three kinds of storage in the C++ memory model: static, automatic, and free store. There is no such thing as "the stack" or "the heap", although automatic storage is frequently implemented using a stack, and the free store is often referred to as "the heap" although rarely is a heap data structure used in its implemtation.

It's pretty important that a C++ programmer know and understand the difference between the three types of storage and the various pitfalls associated with each.

Share this post


Link to post
Share on other sites
rolkA    116
Quote:
Original post by _Sigma
Quote:
Original post by Zahlman
Quote:
And isn't the heap actually managed by malloc/free, and new/delete manage the "free store"?


Yes. Most people can't be bothered to distinguish, though. Although they should.

What is the difference again?


Abstraction.
new/delete are using "the free store", and you don't know how it's implemented. Maybe with "the heap", maybe not.

Share this post


Link to post
Share on other sites
_Sigma    792
Bregma, rolkA: Thanks. I figured I knew it, but decided to sanity check just in case :)

Quote:
and the free store is often referred to as "the heap" although rarely is a heap data structure used in its implemtation.

I didn't know that one tidbit.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this