the different between aaa m1[100] and aaa *p = new [100]

G

Guest

newbie
code
--------------------------
#include <iostream>
using namespace std;
#include <cstring>


class aaa
{
private:
int age;
static int num ;
public:
aaa();
~aaa();
};
aaa::aaa()
{
++num;
cout << " call aaa() one time number =:" << num << endl;
}

aaa::~aaa()
{
--num;
cout << " call ~aaa()one time number =:" << num << endl;
}

int aaa::num =0;
int main()
{
aaa m1[100];
aaa *p = new aaa[100];
;
return 0;
}

----------------------------------
i want to know the deifferent betweent aaa m1[100] and aaa *p = new [100]

aaa m1[100] will call aaa() 100 times and ~aaa() 100 times
but aaa *p = new [100] will call aaa() 100 times and dont call ~aaa()

why??
 
J

John Carson

newbie
code
--------------------------
#include <iostream>
using namespace std;
#include <cstring>


class aaa
{
private:
int age;
static int num ;
public:
aaa();
~aaa();
};
aaa::aaa()
{
++num;
cout << " call aaa() one time number =:" << num << endl;
}

aaa::~aaa()
{
--num;
cout << " call ~aaa()one time number =:" << num << endl;
}

int aaa::num =0;
int main()
{
aaa m1[100];
aaa *p = new aaa[100];
;
return 0;
}

----------------------------------
i want to know the deifferent betweent aaa m1[100] and aaa *p = new
[100]

aaa m1[100] will call aaa() 100 times and ~aaa() 100 times
but aaa *p = new [100] will call aaa() 100 times and dont call ~aaa()

why??

aaa m1[100] is destroyed when it goes out of scope, which happens when
main() is exited.

The 100 instances allocated with new are never destoyed because they never
go out of scope (variables allocated with new never go out of scope). The p
variable does go out of scope when main() is exited, so its destructor would
be called if it had one, but it doesn't have one.

You have two options:

1. Call

delete[] p;

before main() is exited.

2. Use a "smart pointer" rather than a regular pointer. A smart pointer is
an object of a class that functions much the same as a regular pointer but
does have a destructor. This destructor makes the delete[] p; call for you.
 
E

evaned

[code posted below for brevity]
i want to know the deifferent betweent aaa m1[100] and aaa *p = new [100]

aaa m1[100] will call aaa() 100 times and ~aaa() 100 times
but aaa *p = new [100] will call aaa() 100 times and dont call ~aaa()

why??


There are a couple differences between declaring an array and a pointer
to an array.

The one that most concerns your code is that declaring an array (e.g.
aaa m1[100];) makes what's called an automatic variable. When main is
called, space is automagically allocated for m1 and the constructor is
called for each element. When the main function returns, the destructor
is automatically called for each element and the space m1 takes up is
deallocated. Thus you get the 100 messages about the elements in m1
being deallocated.

The same is true for the *pointer* p. When main is called, space for p
is allocated, and when main exits the space is deallocated. (p doesn't
have a constructor or destructor... keep reading.) The problem comes
with the fact that p and what p points to -- the array of aaas -- are
not the same. C++ doesn't care that, when main returns, what p pointed
to is no longer reachable; it just carries right on. Thus the
destructor is never called, and the space the array takes up isn't
deallocated. You have what is called a memory leak, because your
program has memory that is useless (the technical term is garbage) but
that it can't deallocate because it doesn't know it's useless. So it's
wasting it.

You need to add a 'delete[] p;' line before you return from main. This
will call the destructor for each element in the array p points to, and
deallocate the space.


That's not the only differece though. While pointers and arrays are
mostly interchangable, they aren't completely. One difference is what
sizeof() says; sizeof(p) will probably return 4 (depending on the
platform and compiler you are running), while sizeof(m1) might return
400, and will at least return something a couple orders of magnitude
larger than sizeof(p). This is because sizeof(p) knows that p is a
pointer, but knows nothing about what it points to, while m1 is an
array of 100 aaas. Each aaa takes up, say, 4 bytes (since is has
exactly one field, an int, and no virtual functions), so 100 of them
take up 400 bytes. (Your numbers may vary significantly. I didn't even
bother to check if these are what comes out on my system. Take them
with a grain of salt, and try it out yourself to see what they are.
Just add cout << sizeof(stuff); in there, with 'stuff' replaced by aaa,
m1, or p.)


newbie
code
--------------------------
#include <iostream>
using namespace std;
#include <cstring>


class aaa
{
private:
int age;
static int num ;
public:
aaa();
~aaa();
};
aaa::aaa()
{
++num;
cout << " call aaa() one time number =:" << num << endl;
}

aaa::~aaa()
{
--num;
cout << " call ~aaa()one time number =:" << num << endl;
}

int aaa::num =0;
int main()
{
aaa m1[100];
aaa *p = new aaa[100];
;
return 0;
}

----------------------------------
 
R

Richard Cavell

The one that most concerns your code is that declaring an array (e.g.
aaa m1[100];) makes what's called an automatic variable. When main is
called, space is automagically allocated for m1 and the constructor is
called for each element. When the main function returns, the destructor
is automatically called for each element and the space m1 takes up is
deallocated. Thus you get the 100 messages about the elements in m1
being deallocated.

In this vein, what are the practical considerations regarding the
difference between automatic-allocation and new-allocation? That is to
say, on modern implementations, if the compiler uses a stack for
automatic variables and the operating system's innate malloc()-like
function for 'new', what are the limitations regarding size limits,
having to start on a 4/8/16-byte boundary, etc?
 
E

evaned

As far as alignment is concerned, I have no clue. It's platform and
implementation defined, but I can't even give examples; I'm not that
knowledgable about how alignment works or anything like that. Perhaps
someone else can fill that in.

However, typically the heap size is much larger than the stack size. I
think the default stack size is usually about a meg give or take.
However, I've run programs that have used a couple hundred megs of heap
space without changing compiler settings. So your heap is almost
guranteed to be larger.

A couple more things of note: new/malloc takes a little time, because
it has to find an appropriate block of memory. Depending on the
implementation of malloc/delete, this could be anywhere from usually
constant time to linear with the number of unallocated blocks. I don't
know what the glibc version of malloc uses, nor any other common
implementation. I do have Lion's Commentary on Unix here, and looking
at the implementation of malloc in it (a really freaking old copy of
Unix from the PDP11 days), it looks like it uses the first fit
algorithm. This means that it looks through a list of free blocks
(areas of memory that aren't allocated) until it finds one that is at
least large enough to fit the requested size in. In any case, this time
is usually insignificant, but it's worse than "completely free", which
is essentially the case with automatic variables. (I'm ignoring
constructors and any other initialization here.)

Also, there is a bit of space overhead as well. Remember that you don't
pass free() the size of the allocated block, so it must keep that
information somewhere. Often (usually? almost always?) this is kept in
a header before the block. So if you get back p from malloc, there will
be a word at *(p-sizeof(int)) that holds the size of that block.

Also, another point of interest is that usually programs don't release
memory back to the OS until they exit. For instance, my understanding
of the working of glibc is that when malloc is called it goes to the OS
and requests memory from it, gets it, and sets up its own structure in
it of free blocks, and allocates memory. When that memory gets freed
from your code, glibc marks that block as unallocated but doesn't do
anything else. Even if that block was the only allocated space on that
page, it won't return it to the OS. The thinking is that system calls
are expensive, so it's better to avoid them if possible. Chances are
good that if you needed that memory before, you'll need it again.
Practically, this won't provide a problem because if it isn't used the
OS will just swap that page out to disk eventually and it'll be ignored
from then on.

Please note that all of this information is gleaned from somewhat
abstract discussions in classes I've had (pretty much my OS course),
and it's sometimes hard to tell if what we're learning is actually
things that are being done in practice or if there are better ways, and
almost all references to implementations in real systems (e.g. glibc)
are made in passing, so take what I said with a grain of salt.
 
G

Guest

newbie
code
--------------------------
#include <iostream>
using namespace std;
#include <cstring>


class aaa
{
private:
int age;
static int num ;
public:
aaa();
~aaa();
};
aaa::aaa()
{
++num;
cout << " call aaa() one time number =:" << num << endl;
}

aaa::~aaa()
{
--num;
cout << " call ~aaa()one time number =:" << num << endl;
}

int aaa::num =0;
int main()
{
aaa m1[100];
aaa *p = new aaa[100];
;
return 0;
}

----------------------------------
i want to know the deifferent betweent aaa m1[100] and aaa *p = new [100]

aaa m1[100] will call aaa() 100 times and ~aaa() 100 times
but aaa *p = new [100] will call aaa() 100 times and dont call ~aaa()

why??
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top