Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > ctor/dtor calls and ctor init seq

Reply
Thread Tools

ctor/dtor calls and ctor init seq

 
 
Grizlyk
Guest
Posts: n/a
 
      11-25-2006
Good morning.

Look here:
http://groups.google.com/group/fido7...41aba5238c0f79
and here:
http://groups.google.com/group/fido7...014f4ba9df614a

Can anybody answer?

Who can't read in russian:

....
struct T
{
int *a;
T1 b;
T2 c;

void print()const throw();

T()throw(exception&):a(0),b(0){ a=new int[10]; b...=a;}
~T()throw(){ delete[] a; a=0; }
};
....
try{ T obj; obj.b.input(); obj.print(); }catch(...){}
....

Q1: ctor throw exception during init, for ex
T()throw(exception&):
a(0),
b(0), //throw here
/*c()*/
T::ctor user code (in {}) don't start exec. Will T::dtor be called or
no?

Q2: ctor throw exception after init, for ex
T()throw(exception&):a(0), b(0), /*c()*/
{
a=new int[10]; //throw here
b...=a;
}
T::ctor user code (in {}) is partial (not complete) executed. Will
T::dtor be called or no?

Q3: What sequence of class-members, base class and virtual base class
is used for init:
a)seq of appearence in
list of initializers
list of inheritance
class description
b) indefinite order

Answers must be based on appropriate parts of C++ std rules (publish
complete list, pls.

 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-25-2006
* Grizlyk:
> Good morning.

[snip]
>
> Q3: What sequence of class-members, base class and virtual base class
> is used for init:
> a)seq of appearence in
> list of initializers
> list of inheritance
> class description
> b) indefinite order
>
> Answers must be based on appropriate parts of C++ std rules (publish
> complete list, pls.


Please do your HOMEWORK on your own.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
 
 
 
Grizlyk
Guest
Posts: n/a
 
      11-26-2006
Good morning.

>Alf P. Steinbach:
> Please do your HOMEWORK on your own.

The local Pinkerton finds out my real desires - no hide, no run from
him!

Are anybody think another about my question? What is it, even Bazarov
keep silence for subj? Some years ago he wrote certainly something
about __.

 
Reply With Quote
 
David Harmon
Guest
Posts: n/a
 
      11-27-2006
On 25 Nov 2006 20:06:39 -0800 in comp.lang.c++, "Grizlyk"
<(E-Mail Removed)> wrote,
>
>Are anybody think another about my question? What is it, even Bazarov
>keep silence for subj? Some years ago he wrote certainly something
>about __.


This issue is covered in Marshall Cline's C++ FAQ. See the topic
"[17.4] How should I handle resources if my constructors may throw
exceptions?" It is always good to check the FAQ before posting. You
can get the FAQ at:
http://www.parashift.com/c++-faq-lite/


 
Reply With Quote
 
Grizlyk
Guest
Posts: n/a
 
      11-28-2006
> David Harmon ():
> This issue is covered in Marshall Cline's C++ FAQ. See the topic
> "[17.4] How should I handle resources if my constructors may throw
> exceptions?" It is always good to check the FAQ before posting. You
> can get the FAQ at:
> http://www.parashift.com/c++-faq-lite/


"It is always good to check the FAQ before posting." You are right "in
general", but not right for the qwestion. The answer for this is always
short and easy for anybody, who can write C++ more then copying FAQ
examples and more then filling ready class skeleton and who can explain
at least self programs.

It is absolutly unclear why "If a constructor throws an exception, the
object's destructor is not run." One can imagin too diffrent parts of
ctor of any class, they looks like
1. list of initializers
2. code in {}
And there is absolutely no sence to treat exception from them equally.

I think, the nesgroup is group of very busy men. It is better to me to
find other

 
Reply With Quote
 
David Harmon
Guest
Posts: n/a
 
      11-28-2006
On 27 Nov 2006 20:16:20 -0800 in comp.lang.c++, "Grizlyk"
<(E-Mail Removed)> wrote,
>It is absolutly unclear why "If a constructor throws an exception, the
>object's destructor is not run."


If the constructor throws, the object is not completely constructed.
The destructor has no way to know that. A non-trivial destructor would
have no way to know what it needs to do.

If the constructor is going to throw, it should first clean up the
_part_ of the class it has built so far.

>One can imagin too diffrent parts of
>ctor of any class, they looks like
>1. list of initializers


Base classes and members with constructors should have their own
constructors. If some base classes and members have been constructed
when one of them throws, the destructors of the ones already constructed
are automatically run in the reverse order of construction.

>2. code in {}


There is where the "if the constructor throws" really applies. Again,
base classes and members with destructors take care of themselves, so
what you really need to look after there is unfinished business of the
{} code itself. With good RAII design there will not be too much of
that.


 
Reply With Quote
 
David Harmon
Guest
Posts: n/a
 
      11-29-2006
On Tue, 28 Nov 2006 07:05:17 GMT in comp.lang.c++, David Harmon
<(E-Mail Removed)> wrote,
>Base classes and members with constructors should have their own
>constructors.


Should be:

Base classes and members with constructors should have their own
destructors.

 
Reply With Quote
 
BobR
Guest
Posts: n/a
 
      11-29-2006

Grizlyk wrote in message ...
>
>It is absolutly unclear why "If a constructor throws an exception, the
>object's destructor is not run."


When an exception is thrown, it immediately leaves that point and starts
searching for an handler (like a 'catch'). It won't finish what it was doing
(in this case, constructing an object). If an object is not fully
constructed, it has no destructor to call (loosely speaking. See David's
post).

> One can imagin too diffrent parts of
>ctor of any class, they looks like
>1. list of initializers


[Functionlevel try blocks]

class Boom : public Abase{
Boom( int a ) try : Abase(a){}catch(...){/*something*/ throw; }
};

>2. code in {}


class Boom{
int Int;
Boom( int a ){
try{
Int = a;
}
catch(...){/*something*/ throw; }
}
};

>And there is absolutely no sence to treat exception from them equally.
>
>I think, the nesgroup is group of very busy men. It is better to me to
>find other



See: "Thinking In C++" Volume 2: Practical Programming
(Bruce Eckel, Chuck Allison)

Part 1: Building Stable Systems
1: Exception handling

Get "Thinking in C++", 2nd ed. Volume 1&2 by Bruce Eckel
(available for free here. You can buy it in hardcopy too.):
http://www.mindview.net/Books/TICPP/...ngInCPP2e.html

--
Bob R
POVrookie


 
Reply With Quote
 
Grizlyk
Guest
Posts: n/a
 
      11-29-2006
Good morning.

The two last posts: "David Harmon 28.11.2006 10:05 " and "BobR
29.11.2006 05:17 " is really very interesting to me. I will consider
them for nearest time.

And if it is interesting to anybody, i can explain my doubts more:
David Harmon wrote:
"If the constructor throws, the object is not completely constructed."
It is true.
"The destructor has no way to know that."
But it is not true. Programmer, of course, can not control a
construction sequence, but the compiler can know, what the "imagined"
part of constructor failed. Let's consider the next class:

struct A
{
int* a; //need array of int[1024]
int b;
double c;

A()throw(exceprion&); //must allocate memory with new[]
~A()throw(); //must free memory
};

This class has only members of base C++ types. They could not throw
exception while creating own memory or data . They have own
predefined destructors (~int etc), which completele restore system to
state befor the members created and compiler can know about their
destructors and _can calls them if the members were created_.

Lets write simple destructor of the class A:
~A::A()throw(){delete[] a; a=0;}
The destructor of the class A has the one serious trouble - it can not
calls "delete[]" of member "a" befor operator new will return a correct
memory pointer. The data, stored in "a", is indefinite befor new will
return.

If compiler calls the dtor of the class A befor new will return a
correct memory pointer, the program will crash and make at least
"general protection fail".

Selecting way of creation ctor of the class A, we can do like this
A::A()throw(exceprion&):a(0){/*some code*/}
The trick ":a(0)" makes dtor callings safe nearly independent from ctor
code in {}.

It is enough to guess, that compiler _can not_ call dtor of A, if list
of initializers (ctor part one) failed, and _can_ call dtor of A if all
members have been complete created successfully.

There is another important argument to the upper described compiler
behavior: all the class A members of predefined types has own ctor/dtor
pairs, i.e. all the class A members are true classes with full
incapsulated behaviour (they no need external control).

Compiler can manage creating/destroying of the members by "calling"
their trivial ctor/dtor. And executed dtor of any member of the class A
completely restore the piece of system state, which has been changed by
creating the member.

And the ctor "code in {}" of the class A must be managed by compiler in
the same manner. In order to restore all canges, have been created or
partial (not complete) created by ctor "code in {}" execution, compiler
_must_ call its dtor pair, else programmer will have to call dtor by
hand.

I do not see any sence to call destructor code from constructor myself,
for it is can be easy done by compiler.

To do it compiler can create ctor as two "imagined" part: "member_ctor"
and "user_code_ctor". The "member_ctor" code is hidden to programmer,
the correct ctor of any member of the class A is controlled by
programmer with the help of list of initislizers. The goal of the
"member_ctor" - make calls dtor of its class safe. The goal of
"user_code_ctor" is control of its class memory. And dtor parted the
same.

Using the pattern we will have something like this:

{
A obj;
//A::compiled_ctor
// A::member_ctor(); if(exception)goto member_ex
// A::user_code_ctor(); if(exception)goto user_ex

....

//A::compiled_dtor
//user_ex:
// ~A::user_code_dtor();
//member_ex:
// ~A::member_dtor();
}


It is evidently, compiler must _not_ call "user_code_dtor()" if
"user_code_ctor()" is even not started and must call "user_code_ctor()"
if any part of "user_code_dtor()" executed in order to restore system
state.

In my first example any member of the class A has trivial ctor/dtor and
can not throw any exception. Let's consider second example:

struct B
{
A a;
char* b; //need array of char[256]
double c;

B()throw(exceprion&); //must allocate memory with new[]
~B()throw(); //must free memory
};

The class A already can throw exception, but the pattern of its
ctor/dtor creating allows to compiler to use class A as true class
(with its own hidden ctor/dtor behaviour), calling
"A::compiled_ctor"/"A::compiled_dtor" in
"B::member_ctor()"/"B::member_dtor()". The pattern of ctor/dtor allows
to compiler restore all changes maked by partial or complete created
the member A of any class B.

One can see: any class has either members of only predefined types with
their trivial ctor/dtor and can use the ctor/dtor pattern (similar to
the class A), or members like the class B (similar to the class B). For
both cases the ctor/dtor pattern can be used, so destructor code can be
always called by compiler.

I can understand, that my explanaition is quite week and can not be
trusted "in general case".

In order to expand the explanaition to "general case" a man must be an
expert of C++ real programming and know many practical cases, to find
exceptions from my explanation. I do not see any exceptions

Can you object me?

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
A quirk/gotcha of for i, x in enumerate(seq) when seq is empty Alex Willmer Python 14 02-29-2012 12:18 AM
#elements of seq A in seq B Neal Becker Python 2 08-21-2009 06:44 AM
Re: #elements of seq A in seq B Jan Kaliszewski Python 4 08-20-2009 11:25 PM
conditions for automatic generation of default ctor, copy ctor,and default assignment operator (operator) puzzlecracker C++ 8 04-15-2008 09:56 PM
Templates, copy ctor and type-conversion ctor NVH C++ 8 07-06-2006 07:19 PM



Advertisments