Note: Please don't top-post. Consult section 5 of this group's FAQ for
more information.
http://www.parashift.com/c++-faq-lite/
Sean said:
Andrey (and others),
I now see that my question was far too ambiguous. I understand the
difference between std::stack and std::heap as far as looking at each
of those data structures as abstract data types, I just do not
understand how these two data structures are implemented when your C++
code is compiled.
Two points here: First, there is no std::heap, but there are some
functions (such as std::make_heap) for acting on sequences that happen
to be arranged as a heap.
Second, the concept of a "heap" as a data structure seems to be
completely separate from a "heap" as a memory allocation pool. As far as
I can tell there's not any strong similarities between these two things,
they just happen to go by the same name.
What I should've asked is "what is the scope of data when allocated
from the heap, and what is the scope of data when allocated from the
stack (where ``heap'' and ``stack'' are not standards, but are merely
common terms.)
To answer this, I'm going to quote and expand on what Karl said in his
reply:
The scope of memory allocated on the 'stack' is the scope
of the enclosing block. They get destroyed when the enclosing
block is finished. Thats why they are called 'auto' objects.
To this I would add that sometimes the declaration is not physically
inside the block. For example:
int i;
for (int j=0; j<10; ++j)
{
int k;
}
Here, 'j' goes out of scope when the loop finishes, just as 'k' does.
This is different from old "ARM" C++, where 'j' would continue to exist
after the loop, going out of scope at the same time as 'i'. Some
compilers still implement this old rule, and others use their own rule
which allows code using either rule to be accepted (which violates the
standard, by the way).
More from Karl's post:
The scope of memory allocated on the 'heap' is different.
Objects get allocated with new (or malloc) and get destroyed
when a corresponding delete (or free) is executed. Blocks do
no longer influence the scope of these objects.
I want to mention that things that are deallocated with 'free' don't get
"destroyed" in one sense of the word - their destructors don't get
called (unless you do it explicitly). This doesn't always make a
difference, but when it does the difference can be very important. This
is one of the reasons why we usually stick to 'new' and 'delete' in C++.
In fact, you should even avoid 'new' and 'delete' when you can help it.
Explicit memory (or any resource) management is a hassle, and makes it
easy for bugs and lack of exception safety to creep in.
And also, is there a performance difference, in general, of objects
allocated on the stack versus those allocated on the heap, or is this
a completely meaningless question?
Conventional wisdom is that auto (stack) variables are very fast, while
allocating dynamic memory might be slow. In my experience, I've usually
found allocating dynamic memory to be so fast that it doesn't matter
much, but this could depend on several factors. I would suggest not
making speed one of the primary factors in deciding which to use, unless
you have a demonstrated speed problem that can be traced to your memory
allocation.
Allocating an auto variable (one that would be on "the stack") in a
typical C++ implementation using stack frames is a constant time
operation, but the implementation might be able to do even better than
that. Typically, several variables may be allocated at once, and the
entire operation is constant time (this may happen on entry to a
function, and all variables used in the function might be allocated at
this time). Even better, some auto variables might have space reserved
for them when the program begins, so they don't need to be allocated on
"the stack" at all. This only works for auto variables in certain
functions - for example, it won't work for a variable in a function that
is called recursively, where multiple instances of the variable need to
exist simultaneously.
As for dynamic memory... well, I don't know much about typical
implementations of that. But there's been a lot of work done in this
area, and some implementations should be quite fast. I wouldn't expect
it to be as fast as auto variables (it's hard to beat constant-time or
zero-time, after all), but a good implementation should be fast enough
for all but the most extreme situations.
-Kevin