469,267 Members | 1,114 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,267 developers. It's quick & easy.

Memory : Stack vs Heap

Thanks everybody for helping me with the Syntax confusion! The
implicit conversion stuff really got me :) I have one more
question...

Array<int32ia;

Does the above use the default constructor and get me an Array<int32>
with a size 0? The memory used is the stack, right?

ia = Array<int32>(10);

Will my array be on the stack or the heap? Based on my observation
with MSVS 2003, it looks to be on the Heap, but I'd like to be sure
that is indeed the standard!!
Thanks,

===
template<class T>
class Array : public Object
{
public:
explicit Array(int32 aSize = 0) : dataLen(aSize)
{
data = new T[dataLen];
}

explicit Array(const T *aVal, int aSize) : dataLen(aSize)
{
data = new T[dataLen];
for(int32 t = 0; t < dataLen; t++)
data[t] = aVal[t];
}

explicit Array(int32 aSize, const T& aVal) : dataLen(aSize)
{
data = new T[dataLen];
for(int32 t = 0; t < dataLen; t++)
data[t] = aVal;
}

virtual ~Array()
{
delete[] data;
}

int32 length() const
{
return(dataLen);
}

const T& operator[](int32 i) const
{
return(data[i]);
}

T& operator[](int32 i)
{
return(data[i]);
}

T *getData() const
{
return(data);
}

Array& operator=(const Array<T>& aOrig)
{
if(this == &aOrig)
return(*this);

T *newData = new T[aOrig.length()];
for(int32 t = 0; t < aOrig.length(); t++)
newData[t] = aOrig[t];

delete[] data;
dataLen = aOrig.length();
data = newData;

return(*this);
}

private:
Array(const Array<T&aOrig) { aOrig;};

private:
T *data;
int32 dataLen;
};

May 24 '07 #1
9 2274
co*******@yahoo.com wrote:
Thanks everybody for helping me with the Syntax confusion! The
implicit conversion stuff really got me :) I have one more
question...

Array<int32ia;

Does the above use the default constructor and get me an Array<int32>
with a size 0? The memory used is the stack, right?

ia = Array<int32>(10);

Will my array be on the stack or the heap? Based on my observation
with MSVS 2003, it looks to be on the Heap, but I'd like to be sure
that is indeed the standard!!
It depends on what you mean my 'your Array', it has several parts and
some can be on the stack and some of the heap.

In your array class the memory pointed to by data is *always* on the
heap because you allocate it with new. But data, dataLen themselves
could be on the heap or they could be on the stack. It depends on how
you declare your Array variable. In the examples above 'ia' is on the
stack. Here's an example where everything is on the heap

Array<int32>* p = new Array<int32>(10);

Here the array is on the heap (because its allocated with new), and the
data in the array is also on the heap (because it also is allocated with
new). But of course the pointer p itself is on the stack.

It's a common newbie confusion when using pointers, you must clearly
seperate in your mind, the pointer and the data pointed to.

john
May 24 '07 #2
Well, here is my real confusion:

class MyClass
{

private:
Array<32int32Array;
};

MyClass::MyClass() : int32Array(10)
{
}

Now will be entire int32Array(10) be in the heap?

How about:

Array<32>& MyClass:MyFunc()
{
ia = Array<32>(10);
return(ia); // NONO ?
}

The reason I don't use a pointer such as Array<int32*arrayPtr; is
because well, it looks ugly with (*arrayPtr)[0]....if I can avoid that
syntactically, that would be great.
Thanks...

On May 24, 12:14 am, John Harrison <john_androni...@hotmail.com>
wrote:
coder_...@yahoo.com wrote:
Thanks everybody for helping me with the Syntax confusion! The
implicit conversion stuff really got me :) I have one more
question...
Array<int32ia;
Does the above use the default constructor and get me an Array<int32>
with a size 0? The memory used is the stack, right?
ia = Array<int32>(10);
Will my array be on the stack or the heap? Based on my observation
with MSVS 2003, it looks to be on the Heap, but I'd like to be sure
that is indeed the standard!!

It depends on what you mean my 'your Array', it has several parts and
some can be on the stack and some of the heap.

In your array class the memory pointed to by data is *always* on the
heap because you allocate it with new. But data, dataLen themselves
could be on the heap or they could be on the stack. It depends on how
you declare your Array variable. In the examples above 'ia' is on the
stack. Here's an example where everything is on the heap

Array<int32>* p = new Array<int32>(10);

Here the array is on the heap (because its allocated with new), and the
data in the array is also on the heap (because it also is allocated with
new). But of course the pointer p itself is on the stack.

It's a common newbie confusion when using pointers, you must clearly
seperate in your mind, the pointer and the data pointed to.

john

May 25 '07 #3
co*******@yahoo.com wrote:
Well, here is my real confusion:

class MyClass
{

private:
Array<32int32Array;
};

MyClass::MyClass() : int32Array(10)
{
}

Now will be entire int32Array(10) be in the heap?
I'm sorry but it depends. When something is in a class, it will be on
the heap if the containing object is on the heap, and on the stack if
the containing object is on the stack.

>
How about:

Array<32>& MyClass:MyFunc()
{
ia = Array<32>(10);
return(ia); // NONO ?
Well that's not legal because ia is not declared, but assuming you meant

Array<32>& MyClass:MyFunc()
{
Array<32ia(10);
return(ia);
}

then you are returning a reference to an object on the stack, a big fat
NO NO!
}

The reason I don't use a pointer such as Array<int32*arrayPtr; is
because well, it looks ugly with (*arrayPtr)[0]....if I can avoid that
syntactically, that would be great.
OK, here's the real answer to you dilimma.

1) Write the natural code (almost always a good idea)

Array<32MyClass:MyFunc()
{
Array<32ia(10);
return(ia);
}

2) Now you're probably saying, 'but that copies the entire array, it's
very inefficient'.

So the answer is to make the copying of your Array class more efficient.
You do this with a technique called 'reference counting' and 'copy on
write' (also known as COW). These techniques will let you return any
sized object from a function at not much more cost than copying a pointer.

Too long to explain these techniques here, but google for them. Or buy
the books 'Effective C++' and 'More Effective C++' by Scott Meyers, two
of the best books on C++ ever written. Here deals specifically with
these issues, and a lot of other good stuff besides.

john
May 25 '07 #4
I like this and I will head out to the store for "Effective C++". I
got "Effective C" already :)

I "know" about COW, but wouldn't MyFunc() automatically make a copy
immediately upon return? Perhaps, I really need to re-read (too many
years of Java:) Fundamental C++ again...

Thanks...
1) Write the natural code (almost always a good idea)

Array<32MyClass:MyFunc()
{
Array<32ia(10);
return(ia);

}

2) Now you're probably saying, 'but that copies the entire array, it's
very inefficient'.

So the answer is to make the copying of your Array class more efficient.
You do this with a technique called 'reference counting' and 'copy on
write' (also known as COW). These techniques will let you return any
sized object from a function at not much more cost than copying a pointer.

Too long to explain these techniques here, but google for them. Or buy
the books 'Effective C++' and 'More Effective C++' by Scott Meyers, two
of the best books on C++ ever written. Here deals specifically with
these issues, and a lot of other good stuff besides.

john

May 26 '07 #5
co*******@yahoo.com wrote:
I like this and I will head out to the store for "Effective C++". I
got "Effective C" already :)

I "know" about COW, but wouldn't MyFunc() automatically make a copy
immediately upon return? Perhaps, I really need to re-read (too many
years of Java:) Fundamental C++ again...
MyFunc would make a copy (that is, it would call the copy constructor),
but the point about COW is that the real copy is delayed until someone
writes to the array. That isn't going to happen just by returning an
Array from a method.

BTW COW (and refernce counting) is in More Effective C++.

john
>
Thanks...
>1) Write the natural code (almost always a good idea)

Array<32MyClass:MyFunc()
{
Array<32ia(10);
return(ia);

}

2) Now you're probably saying, 'but that copies the entire array, it's
very inefficient'.

So the answer is to make the copying of your Array class more efficient.
You do this with a technique called 'reference counting' and 'copy on
write' (also known as COW). These techniques will let you return any
sized object from a function at not much more cost than copying a pointer.

Too long to explain these techniques here, but google for them. Or buy
the books 'Effective C++' and 'More Effective C++' by Scott Meyers, two
of the best books on C++ ever written. Here deals specifically with
these issues, and a lot of other good stuff besides.

john

May 26 '07 #6
co*******@yahoo.com wrote:
:: I like this and I will head out to the store for "Effective C++".
:: I got "Effective C" already :)
::
:: I "know" about COW, but wouldn't MyFunc() automatically make a copy
:: immediately upon return? Perhaps, I really need to re-read (too
:: many years of Java:) Fundamental C++ again...

There is another twist to this exact example, as the compiler is
allowed to "elide" the copying of return values, and construct the
value directly into the receiving variable. Look for "NRVO".

If you do

Array<32target = mc.MyFunc();

the resulting code MIGHT be exactly the same as if you had written

Array<32target(10);

Guessing about optimization is just close to impossible. Therefore
"Write the natural code" really is the best advice.
::
:: Thanks...
::
::: 1) Write the natural code (almost always a good idea)
:::
::: Array<32MyClass:MyFunc()
::: {
::: Array<32ia(10);
::: return(ia);
:::
::: }
:::
::: 2) Now you're probably saying, 'but that copies the entire array,
::: it's very inefficient'.

Or it is not! :-)
Bo Persson
May 26 '07 #7
I think my "real" C++ neutrons are starting to fire:) Well, up until
recently, I have always used C++ like a super C with classes. That
is, copy constructor/assignment operators were always private and all
object instantiation were done with "new", so I knew exactly when and
where an object was, ie. heap or stack. Now, that I started to use
Array templates, I find that "natural" (no pointers?:)) code looks and
feel best. Ie...option 1 below looks better than option2

1. Array<int32ia(10); ia[0] = 100;
2. Array<int32*ia1 = new Array<int32>(10); (*ia1)[0] = 100;

Well, option 1 opened up a can of wormy questions for me:) So, if I
understood things right, the memory space for class members is the
same memory space as the containing class. Ie. if the containing
class is all in heap, then all members (recursively) will be on heap.
Well,

class X
{
X(){}
void myFunc() { ia = Array<int32>(10);}
Array<int32ia;
};

int main()
{
X x;
}

Please help (I perused a few books, but I could not find a definitive
answer):

1. ia will first be instantiated with the default constructor in X(),
and that copy will be thrown away and replaced with a new copy in
myFunc()? That seems a bit wasteful. With a pointer, I would not
have to instantiate ia until I need to allocate space for me.

2. Will x be on the stack? And will ia be on the stack too? But if X
contained other members and those members contained yet other member
objects, wouldn't we run the risk of inadvertently blow the stack?

3. From 2, so to avoid blowing the stack, main() should start with a X
*x = new X() ? So that all subsequent allocations will all be on the
heap?

Thanks!!!

On May 26, 2:02 am, "Bo Persson" <b...@gmb.dkwrote:
coder_...@yahoo.com wrote:

:: I like this and I will head out to the store for "Effective C++".
:: I got "Effective C" already :)
::
:: I "know" about COW, but wouldn't MyFunc() automatically make a copy
:: immediately upon return? Perhaps, I really need to re-read (too
:: many years of Java:) Fundamental C++ again...

There is another twist to this exact example, as the compiler is
allowed to "elide" the copying of return values, and construct the
value directly into the receiving variable. Look for "NRVO".

If you do

Array<32target = mc.MyFunc();

the resulting code MIGHT be exactly the same as if you had written

Array<32target(10);

Guessing about optimization is just close to impossible. Therefore
"Write the natural code" really is the best advice.

::
:: Thanks...
::
::: 1) Write the natural code (almost always a good idea)
:::
::: Array<32MyClass:MyFunc()
::: {
::: Array<32ia(10);
::: return(ia);
:::
::: }
:::
::: 2) Now you're probably saying, 'but that copies the entire array,
::: it's very inefficient'.

Or it is not! :-)

Bo Persson

May 26 '07 #8
co*******@yahoo.com wrote:
I think my "real" C++ neutrons are starting to fire:) Well, up until
recently, I have always used C++ like a super C with classes. That
is, copy constructor/assignment operators were always private and all
object instantiation were done with "new", so I knew exactly when and
where an object was, ie. heap or stack. Now, that I started to use
Array templates, I find that "natural" (no pointers?:)) code looks and
feel best. Ie...option 1 below looks better than option2

1. Array<int32ia(10); ia[0] = 100;
2. Array<int32*ia1 = new Array<int32>(10); (*ia1)[0] = 100;

Well, option 1 opened up a can of wormy questions for me:) So, if I
understood things right, the memory space for class members is the
same memory space as the containing class. Ie. if the containing
class is all in heap, then all members (recursively) will be on heap.
Well,

class X
{
X(){}
void myFunc() { ia = Array<int32>(10);}
Array<int32ia;
};

int main()
{
X x;
}

Please help (I perused a few books, but I could not find a definitive
answer):

1. ia will first be instantiated with the default constructor in X(),
and that copy will be thrown away and replaced with a new copy in
myFunc()? That seems a bit wasteful. With a pointer, I would not
have to instantiate ia until I need to allocate space for me.
Yes. Wasteful? That depends.
>
2. Will x be on the stack? And will ia be on the stack too? But if X
contained other members and those members contained yet other member
objects, wouldn't we run the risk of inadvertently blow the stack?
Yes, but the internals of X may or may not be. It depends on how X is
written. If X contains a pointer, then the pointer will be on the stack,
*but* what is pointed to may or may not be.

3. From 2, so to avoid blowing the stack, main() should start with a X
*x = new X() ? So that all subsequent allocations will all be on the
heap?

The danger you're talking about doesn't really exist. Consider

class X
{
X(){}
void myFunc() { ia = Array<int32>(10);}
Array<int32ia;
};

template <T>
class Array
{
public:
Array(int n) { data = new T[n]; }
private:
T* data;
};

Array is four bytes big, it's only a pointer. Similarly X is only four
bytes big. So

int main()
{
X x;
}

That's only four bytes of the stack, the remaining 40 bytes
(10*sizeof(int32)) is on the heap, always, because it is allocated with
new. I still not sure you've grasped this. The danger of blowing the
stack in the way you've described is almost non-existant.

john
May 26 '07 #9
On 26 Maj, 22:54, coder_...@yahoo.com wrote:
I think my "real" C++ neutrons are starting to fire:) Well, up until
recently, I have always used C++ like a super C with classes. That
is, copy constructor/assignment operators were always private and all
object instantiation were done with "new", so I knew exactly when and
where an object was, ie. heap or stack. Now, that I started to use
Array templates, I find that "natural" (no pointers?:)) code looks and
feel best. Ie...option 1 below looks better than option2

1. Array<int32ia(10); ia[0] = 100;
2. Array<int32*ia1 = new Array<int32>(10); (*ia1)[0] = 100;
It certainly does. Also it is faster with one less allocation. What
confuses you is perhaps that the
>
Well, option 1 opened up a can of wormy questions for me:) So, if I
understood things right, the memory space for class members is the
same memory space as the containing class. Ie. if the containing
class is all in heap, then all members (recursively) will be on heap.
Yes. A member of an object will always be in the same location as the
object itself.
The pointer "data" in your original class is a member of your class,
so if the Array<is placed on the heap then so will data. What might
confuse you is that what data points to does not belong to your class.
It is owned by your class, but it is not part of it. And that data is
allocated via new and will thus always be on the heap.
Well,

class X
{
X(){}
void myFunc() { ia = Array<int32>(10);}
Array<int32ia;

};

int main()
{
X x;

}

Please help (I perused a few books, but I could not find a definitive
answer):

1. ia will first be instantiated with the default constructor in X(),
and that copy will be thrown away and replaced with a new copy in
myFunc()? That seems a bit wasteful. With a pointer, I would not
have to instantiate ia until I need to allocate space for me.
This is correct. There will be a copy, and the original Array will be
thrown away. Thus, the statement:
ia = Array<int32>(10);
will create a temporary Array with ten copies in it, invoke your
assignment operator and destroy the temporary Array. This is two calls
to new + the overhead with copying the elements.
But you can avoid this by using a neat trick - namely by swapping. You
should write a new procedure that swaps two Arrays - something like:

template <typename T>
void swap(Array<T>& one,Array<T>& other)
{
std::swap(one.data,other.data);
std::swap(one.dataLen,other.dataLen);
}

This will not work out of the box as e.g. you don't have access to
data and dataLen which are private, so you would have to make swap a
member function, and you would also have to create a swap function for
your baseclass (and there is more work to to if you want to make swap
available to others in a generic fashion). Still this should give you
an idea of how to do it.

The upcoming C++ standard (C++0x) is going to solve some of these
problems via move constructors. You will still have to do write the
move constructor yourself, however.
>
2. Will x be on the stack? And will ia be on the stack too? But if X
contained other members and those members contained yet other member
objects, wouldn't we run the risk of inadvertently blow the stack?
Yes they will both be on the stack, but remember the objects are not
that large. Array<Tuses no more than eight bytes if I guess your
architecture correctly, so that is only 16 bytes of stack storage. In
general, objects do not get that large, and I would not worry about
such stuff if I were you.
>
3. From 2, so to avoid blowing the stack, main() should start with a X
*x = new X() ? So that all subsequent allocations will all be on the
heap?
That would save you eight bytes of stack storage, but it will cost
more heap storage and so it is a bad idea. Using pointers not only
looks more kludgey, it will also give you lots of problems with regard
to e.g. exception safety, and in general there will be lots of
housekeeping to do.
One last thing worth mentioning is to always initialise in your
constructor.

Array<intia;
ia = Array<int>(10);

is two calls to new, and one copy.

Array<intia(10);

does the same and is half the work.

Of - and one more thing: Do use std::vector for your normal work.
std::vector is thoroughly tested and much more flexible than your
Array class, and it only uses twelve bytes of storage on your
architecture (unless I guessed wrong again). Also, all of the
infrastructure - such as swapping - is already in place.

/Peter

May 26 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by CoderGuy | last post: by
8 posts views Thread by vikram | last post: by
5 posts views Thread by bull | last post: by
reply views Thread by CoderGuy | last post: by
53 posts views Thread by fdmfdmfdm | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.