operator new question

J

john sun

hello,

When we use new operator to user defined type, constructor will be called
and a memory block is created in heap. My question: where those non-pointer
data members belonging to this user-defined class will be create? on heap or
on stack? Obviousely it's on heap.

OK, if it's on heap, how stack unwinding meachnism can destroy those data
members when exception happened? Since it's not on stack, it's on heap!

I read the c++ progamming language by BStroustrup and can not find the
answer, please help understanding. Thanks very much!

John
 
P

Peter Koch Larsen

john sun said:
hello,

When we use new operator to user defined type, constructor will be called
and a memory block is created in heap. My question: where those non-pointer
data members belonging to this user-defined class will be create? on heap or
on stack? Obviousely it's on heap.

OK, if it's on heap, how stack unwinding meachnism can destroy those data
members when exception happened? Since it's not on stack, it's on heap!

I read the c++ progamming language by BStroustrup and can not find the
answer, please help understanding. Thanks very much!

John
Well..... all members of the object will be stored in the heap, regardless
of whether they are pointers or not. Also, a pointer has no destructor so
nothing happens if it leaves scope:

class C {...};
void test()
{
C c_stack;
C* c_ptr = new C();
if (...)
throw 0;
}

When test returns (or throws), the destructor of c_stack will be called.
c_ptr is not an object (it is a plain pointer) so there will be a memory
leak and a live object somewhere, possible holding on to other ressources.

In short, only use pointer variables when you want to create an object with
a scope reaching outside the point, where it is created. Also in those cases
you should wrap the pointer in a smart-pointer class such as the ones you
can find at boost.

Kind regards
Peter Koch Larsen
 
R

Ron Natalie

john sun said:
hello,

When we use new operator to user defined type, constructor will be called
and a memory block is created in heap. My question: where those non-pointer
data members belonging to this user-defined class will be create? on heap or
on stack? Obviousely it's on heap.

The non-static members (pointer or otherwise) will be created with the object
(i.e., on the heap). Don't confuse a pointer with the object it points to. If
there is a member that is a pointer, then the object it points to is whatever the
class sets it to.
 
R

Rolf Magnus

john said:
hello,

When we use new operator to user defined type, constructor will be
called and a memory block is created in heap.

Yes, though the C++ standard doesn't actually call it heap.
My question: where those
non-pointer data members belonging to this user-defined class will be
create? on heap or on stack? Obviousely it's on heap.
Yes.

OK, if it's on heap, how stack unwinding meachnism can destroy those
data members when exception happened? Since it's not on stack, it's on
heap!

Stack unwinding doesn't have anything to do with dynamically allocated
objects. It rather destroys the local variables of a function when an
exception occurs during that function.
 
N

Nick Hounsome

john sun said:
hello,

When we use new operator to user defined type, constructor will be called
and a memory block is created in heap. My question: where those non-pointer
data members belonging to this user-defined class will be create? on heap or
on stack? Obviousely it's on heap.

OK, if it's on heap, how stack unwinding meachnism can destroy those data
members when exception happened? Since it's not on stack, it's on heap!

Put something on the stack that will delete it for you.

Have a look at std::auto_ptr.

void f()
{
auto_ptr<T> p = new T;
if( error )
throw "error";
}

However the function exits the T will be deleted.
 
J

john sun

here is example:
#include "stdafx.h"
#include <stdio.h>
#include <memory>
using namespace std;

class O
{
public:
O(){};
~O(){};
}
;
class A1
{
O* o;
public :
A1()
{
o=new O();
printf("in A1 ctor\n");
}
~A1()
{
delete o;
printf("in A1 dtor\n");
};
};

class A
{
public :
A(){printf("in A ctor\n");};
~A(){printf("in A dtor\n");};
};
class B
{

auto_ptr<A> a;
A1 a1;
public:
B():a(new A)
{
throw 1;
}
~B(){printf("in B dtor\n");}
};


int main(int argc, char* argv[])
{
try{
B *b=new B();
}
catch(int)
{
printf("catch block\n");
}
return 0;
}


After running a1 and a destructor will be called. This confused me. Since b
is created in heap, and a and a1 is also on heap, how come exception can
call a1 and a's destructor.

Thanks for furthermore clarifying.

Best regards to all!
 
R

Ron Natalie

Fortunately
After running a1 and a destructor will be called. This confused me. Since b
is created in heap, and a and a1 is also on heap, how come exception can
call a1 and a's destructor.
First, there is the concept of a "fully constructed object". An object is
fully constructed when its constructor body has been run. When an exception
happens during object creation, all the things that are fully constructed get
their destructors run.

In this case what happens when you call new B:

1. sizeof(B) bytes is allocated by the global operator new.
2. B's subobjects are constructed. B::a is constructed by dynamically
creating an A object (I'll omit the details of this) dynamically and feeding
it to the auto_ptr constructor. B::a is now fully constructed at this point.
3. B::a1 is default constructed. B::a1 is now fully constructed.
4. The constructor body of B is run.
5. The throw expression is encountered.
6. The compiler now destructs all of the fully constructed parts of B in reverse order:
B::a1 is destroyed.
7. B::a is destroyed, the auto_ptr destructor deletes the referenced A object.
8. The global operator delete is called to return the memory used by B.
9. The stack is unwound up to the point where the handler is found... and control
is transferred there.
 
J

john sun

Thanks Ron!

I know those steps, I am confused the fully constructed object could be
destructed. Since those fully constructed object is on the heap in my
example. If you say fully constructed object can be destructed there should
be some limitations. Because the following code also demo the fully
constructed object will not be destroyed.

class A{};

void foo()
{
A * a=new A();
throw 1;
return 0;
}

int main{
try {
foo();
}
catch(...)
{};
return 0;
}

Object pointed by a will not be deleted even it's a fully constructed
object. I know because c++ lost track of a pointed object. But why in our
previous example, the sub object which is also created on heap will be
deleted if exception throw? Looks like to me c++ can track the subobject
what even it's created on heap or stack. What's the mechanism here?

Thanks very much for sharing and insightful discussion

John
 
N

Nick Hounsome

john sun said:
Thanks Ron!

I know those steps, I am confused the fully constructed object could be
destructed. Since those fully constructed object is on the heap in my
example. If you say fully constructed object can be destructed there should
be some limitations. Because the following code also demo the fully
constructed object will not be destroyed.

class A{};

void foo()
{
A * a=new A();

replace with "std::auto_ptr<A> a = new A; " and it will be destructed.
- A* is a pointer which has no destructor.
 

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

Forum statistics

Threads
474,159
Messages
2,570,879
Members
47,414
Latest member
GayleWedel

Latest Threads

Top