473,320 Members | 1,958 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

More effective C++

I was just going through this book by Scott Meyers and did not fully
follow item 10.
Basically he says the constructor should catch all exceptions, do any
cleanups necessary and then throw. This is because otherwise the member
objects already created can not be destroyed from outside since the
container object itself is not fully created.

Look at this - (myclass contains objects of class1 and class2)
Class myclass {
class1 m_class1;
class2 m_class2;
public:
myclass(int c1, int c2):m_class1(c1), m_class2(c2) {}
}

Assume both class1 and class2 have constructors which take int
parameters.
so m_class1 gets initialized first and then m_class2. If the contructor
of class2 throws an exception, even after its own cleanup, how would it
help? m_class1 is already contructed. How is it destroyed?

I actually tried this on VC++ 6 compiler and it seems to work. As in ,
m_class1's destructor indeed gets called! I think class1 and class2
initializations are independently happening and we can not cleanup one
because of an exception in the other.

Please let me know if I am missing something here. How does the
compiled code know that m_class1 is contructed and it needs to be
destroyed whereas it passes the exception from m_class2 as is.

Jun 15 '06 #1
15 1974
vi************@yahoo.com wrote:

Assume both class1 and class2 have constructors which take int
parameters.
so m_class1 gets initialized first and then m_class2. If the contructor
of class2 throws an exception, even after its own cleanup, how would it
help? m_class1 is already contructed. How is it destroyed?


The compiler generates code that destroys it. The cleanup you need to do
in response to an exception in a constructor is for things that don't
have appropriate destructors.

--

Pete Becker
Roundhouse Consulting, Ltd.
Jun 15 '06 #2
> The cleanup you need to do
in response to an exception in a constructor is for things that don't
have appropriate destructors.


Thanks for the response. But I will have to disagree a bit. Infact in
the example he has given in the book the cleanup code has
delete theImage;
etc where theImage is an object with a welldefined dtor.

--Vikram

Jun 15 '06 #3
> The cleanup you need to do
in response to an exception in a constructor is for things that don't
have appropriate destructors.


Thanks for the response. But I will have to disagree a bit. Infact in
the example he has given in the book the cleanup code has
delete theImage;
etc where theImage is an object with a welldefined dtor.

--Vikram

Jun 15 '06 #4
vi************@yahoo.com schrieb:
The cleanup you need to do
in response to an exception in a constructor is for things that don't
have appropriate destructors.
Thanks for the response. But I will have to disagree a bit. Infact in
the example he has given in the book the cleanup code has
delete theImage;
etc where theImage is an object with a welldefined dtor.


The example in the book dynamically allocates memory with "new". The
code snippet you have posted doesn't. Note the difference.
Therefore, you need to delete theImage explicitly (at this point, the
dtor of theImage will be called). When using new, you have the
responsibility clear the memory on your own (but you could use something
as boost::shared_ptr and give the responsibility of deletion to this
class).
--Vikram


hth,
Gernot
Jun 15 '06 #5
In message <11**********************@r2g2000cwb.googlegroups. com>,
vi************@yahoo.com writes
The cleanup you need to do
in response to an exception in a constructor is for things that don't
have appropriate destructors.


Thanks for the response. But I will have to disagree a bit. Infact in
the example he has given in the book the cleanup code has
delete theImage;
etc where theImage is an object with a welldefined dtor.


Nope. theImage is a *pointer* to such an object. Pointers don't have
destructors, so _you_ have to arrange that the object it points to gets
destroyed, by calling delete.
--
Richard Herring
Jun 15 '06 #6
> The example in the book dynamically allocates memory with "new". The
code snippet you have posted doesn't. Note the difference.
Therefore, you need to delete theImage explicitly (at this point, the
dtor of theImage will be called). When using new, you have the
responsibility clear the memory on your own (but you could use something
as boost::shared_ptr and give the responsibility of deletion to this
class).


Thanks Gernot. Yes, you are right about the example in the book. I was
trying to demonstrate my confusion using objects rather than pointers
because the book specifically says pointers better have a try/catch
blocks for initializations, either in constructor or in a private
member function. Please have a look at the initImage/initAudioImage
methods on page 73 (atleast for the version of the book I have).

In short, I am fine with all the examples that the book has. But I had
a question regarding the whole concept when we have member
initialization lists. How does the code know that m_class1 is already
constructed and should be destroyed? The destructor of the container
object does not get called since it has thrown an exception. So how it
figure out the member objects that are fully created?

Thanks,
Vikram

Jun 15 '06 #7

<vi************@yahoo.com> wrote in message
news:11**********************@p79g2000cwp.googlegr oups.com...
The example in the book dynamically allocates memory with "new". The
code snippet you have posted doesn't. Note the difference.
Therefore, you need to delete theImage explicitly (at this point, the
dtor of theImage will be called). When using new, you have the
responsibility clear the memory on your own (but you could use something
as boost::shared_ptr and give the responsibility of deletion to this
class).


Thanks Gernot. Yes, you are right about the example in the book. I was
trying to demonstrate my confusion using objects rather than pointers
because the book specifically says pointers better have a try/catch
blocks for initializations, either in constructor or in a private
member function. Please have a look at the initImage/initAudioImage
methods on page 73 (atleast for the version of the book I have).

In short, I am fine with all the examples that the book has. But I had
a question regarding the whole concept when we have member
initialization lists. How does the code know that m_class1 is already
constructed and should be destroyed? The destructor of the container
object does not get called since it has thrown an exception. So how it
figure out the member objects that are fully created?


Hi Vikram,

an initialization list is not the same as code in the constructor body.
Those member object initializers you show [:m_class1(c1), m_class2(c2)] are
not normal function calls. They're more like instructions to the compiler
as to _how_ the member objects should be initialized at construction time.
So the normal rules still apply for construction and destruction (and thus
the automatic calling of contructors and destructors).

During construction, the members are constructed for you, in the order
they are declared in the class (which need not be the same as the order of
your initialization list, by the way). When the class is destroyed, the
members are deconstructed in reverse order, and then the class object itself
is destroyed. So all destructors get called automatically.

It's only when you do dynamic allocations in your constructor (e.g.,
using new) that you need to worry about making sure you call delete in the
event of a failure in the constructor.

-Howard


Jun 15 '06 #8

For me, the most annoying aspects of C++ are:

- It's hard to spell.
- It's not Delphi (or Java, or VB).
- There's always that terrible nagging fear that, should I invoke Undefined
Behavior (TM), my hard drive might catch fire, my email system send nasty
messages to my boss, or I could accidently launch a Titan III missile at
China, starting World War 3.

Oh yeah, there's that annoying part about getting paid too much, too...

-Howard
Jun 15 '06 #9

"Howard" <al*****@hotmail.com> wrote in message news:6xfkg.28520

oops, wrong thread... <Cancel!><Cancel!!><Cancel!!!>...arrgh!

(Now ask me about the most annoying things about Outlook Express...)
Jun 15 '06 #10
Howard wrote:
"Howard" <al*****@hotmail.com> wrote in message news:6xfkg.28520

oops, wrong thread... <Cancel!><Cancel!!><Cancel!!!>...arrgh!

(Now ask me about the most annoying things about Outlook Express...)


LOL... THE Most annoying thing about comp.lang.c++:
- All that whining about what's the most annoying thing in C++.
The second most annoying thing about comp.lang.c++:
- All those "questions" whether the asker should learn C++ or Java.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 15 '06 #11
> an initialization list is not the same as code in the constructor body.
Those member object initializers you show [:m_class1(c1), m_class2(c2)] are
not normal function calls. They're more like instructions to the compiler
as to _how_ the member objects should be initialized at construction time.
So the normal rules still apply for construction and destruction (and thus
the automatic calling of contructors and destructors).

During construction, the members are constructed for you, in the order
they are declared in the class (which need not be the same as the order of
your initialization list, by the way). When the class is destroyed, the
members are deconstructed in reverse order, and then the class object itself
is destroyed. So all destructors get called automatically.

It's only when you do dynamic allocations in your constructor (e.g.,
using new) that you need to worry about making sure you call delete in the
event of a failure in the constructor.


Hi Howard, I understand all of the above except for the line
"When the class is destroyed, the members are deconstructed in reverse
order, and then the class object itself is destroyed. So all
destructors get called automatically."
The problem here is the main container class (myClass in my example) is
never destroyed. If the main destructor was being called, I fully
understand how the contained objects' destructors would be called.

Anyway, looks like I am making it more complicated than what it is. Let
me think for a while and if I still dont follow, I will get back with a
better example and specific questions.

Thanks to all who replied.
--Vikram

Jun 16 '06 #12
> Hi Howard, I understand all of the above except for the line
"When the class is destroyed, the members are deconstructed in reverse
order, and then the class object itself is destroyed. So all
destructors get called automatically."
The problem here is the main container class (myClass in my example) is
never destroyed. If the main destructor was being called, I fully
understand how the contained objects' destructors would be called.

Anyway, looks like I am making it more complicated than what it is. Let
me think for a while and if I still dont follow, I will get back with a
better example and specific questions.

Thanks to all who replied.
--Vikram


The reason the "main container class" is never destroyed is because
it's never constructed (fully). If the destructor was called you
wouldn't know which part of the object was constructed (and should be
destroyed) and which parts was not constructed and therefore shouldn't
be destroyed. The only place where you (or the compiler) knows which
parts of the object has been constructed is in the constructor.

There is actually two cases here:

1. An exception is thrown in the construction of any of the possible
base objects (class A : public Base { /* ... */ }; ) or any of the
member objects (either specified in the initialization list or just
default constructed if not part of the list). In this case the compiler
knows what to do and calls the destructor of all objects contructed so
far in reverse order. And the contructor body of your class i never
called. This means any contruction that should have taken place there
is not performed and therefore you don't need to call the destructor.

2. If all base and member objects are contructed ok, the contructor
body of your class is reached. In this case you have to be careful
since if you make any resource allocations (like memory with new) and
something makes your contructor throw later in the construcotr, your
destructor is *not* called since the object is not fully contructed.
You therefore have to guard the contructor code with try/catch (or use
RAII objects like smart pointers - auto_ptr or boost::shared_ptr which
are automaticall destroyed) and destroy any objects allocated so far
manually with delete or similar.

/ Påhl

Jun 16 '06 #13
On 2006-06-15, vi************@yahoo.com <vi************@yahoo.com> wrote:
The example in the book dynamically allocates memory with "new". The
code snippet you have posted doesn't. Note the difference.
Therefore, you need to delete theImage explicitly (at this point, the
dtor of theImage will be called). When using new, you have the
responsibility clear the memory on your own (but you could use something
as boost::shared_ptr and give the responsibility of deletion to this
class).

[snip]
In short, I am fine with all the examples that the book has. But I had
a question regarding the whole concept when we have member
initialization lists. How does the code know that m_class1 is already
constructed and should be destroyed? The destructor of the container
object does not get called since it has thrown an exception. So how it
figure out the member objects that are fully created?
The compiler has the responsibility to figure this out and to destroy the
objects that it has created for you. It allocates memory for your members and
constructs them either by using a constructor without parameters or a
specialized one if you have stated one or more arguments in the initialization
list. When the object's lifetime is over, it destroys these member objects.

When an object cannot be build due to an exception, the desctructor will not
be called, as you mention correctly. This is due to the fact that the object
never was really "alive". In this case, the compiler will destruct members
that were successfully created by the compiler when the constructor is
left due to an exception.
Thanks,
Vikram


Regards,
Gerno
Jun 17 '06 #14
On 2006-06-15, vi************@yahoo.com <vi************@yahoo.com> wrote:
The example in the book dynamically allocates memory with "new". The
code snippet you have posted doesn't. Note the difference.
Therefore, you need to delete theImage explicitly (at this point, the
dtor of theImage will be called). When using new, you have the
responsibility clear the memory on your own (but you could use something
as boost::shared_ptr and give the responsibility of deletion to this
class).

[snip]
In short, I am fine with all the examples that the book has. But I had
a question regarding the whole concept when we have member
initialization lists. How does the code know that m_class1 is already
constructed and should be destroyed? The destructor of the container
object does not get called since it has thrown an exception. So how it
figure out the member objects that are fully created?
The compiler has the responsibility to figure this out and to destroy the
objects that it has created for you. It allocates memory for your members and
constructs them either by using a constructor without parameters or a
specialized one if you have stated one or more arguments in the initialization
list. When the object's lifetime is over, it destroys these member objects.

When an object cannot be build due to an exception, the desctructor will not
be called, as you mention correctly. This is due to the fact that the object
never was really "alive". In this case, the compiler will destruct members
that were successfully created by the compiler when the constructor is
left due to an exception.
Thanks,
Vikram


Regards,
Gerno
Jun 17 '06 #15
On 2006-06-15, vi************@yahoo.com <vi************@yahoo.com> wrote:
The example in the book dynamically allocates memory with "new". The
code snippet you have posted doesn't. Note the difference.
Therefore, you need to delete theImage explicitly (at this point, the
dtor of theImage will be called). When using new, you have the
responsibility clear the memory on your own (but you could use something
as boost::shared_ptr and give the responsibility of deletion to this
class).

[snip]
In short, I am fine with all the examples that the book has. But I had
a question regarding the whole concept when we have member
initialization lists. How does the code know that m_class1 is already
constructed and should be destroyed? The destructor of the container
object does not get called since it has thrown an exception. So how it
figure out the member objects that are fully created?
The compiler has the responsibility to figure this out and to destroy the
objects that it has created for you. It allocates memory for your members and
constructs them either by using a constructor without parameters or a
specialized one if you have stated one or more arguments in the initialization
list. When the object's lifetime is over, it destroys these member objects.

When an object cannot be build due to an exception, the desctructor will not
be called, as you mention correctly. This is due to the fact that the object
never was really "alive". In this case, the compiler will destruct members
that were successfully created by the compiler when the constructor is
left due to an exception.
Thanks,
Vikram


Regards,
Gernot
Jun 17 '06 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

303
by: mike420 | last post by:
In the context of LATEX, some Pythonista asked what the big successes of Lisp were. I think there were at least three *big* successes. a. orbitz.com web site uses Lisp for algorithms, etc. b....
15
by: Riko Wichmann | last post by:
Dear all, is there a way in Python to comment out blocks of code without putting a # in front of each line? Somethings like C's /* block of code here is commented out */ Thanks,
5
by: Ross Presser | last post by:
As our customers demand that we tighten our IT security in the company, I've been asked to prepare a report quarterly showing, for each user in Active directory, what his effective permissions are...
4
by: cfchou | last post by:
hi, i have one question about the item 31 of Meyers' More Effective c++. in page 234, section "Using Virtual Functions Only", it says that "for example, you decide to add a new class Satellite...
116
by: Mike MacSween | last post by:
S**t for brains strikes again! Why did I do that? When I met the clients and at some point they vaguely asked whether eventually would it be possible to have some people who could read the data...
44
by: Josh Mcfarlane | last post by:
Just out of curiosity: When would using std::list be more efficient / effective than using other containers such as vector, deque, etc? As far as I'm aware, list doesn't appear to be...
0
windows_mss
by: windows_mss | last post by:
Hi programmer's, Using Transactions in Windows application is more effective or using transaction in Web Application is More effective ? Thanks in Advance
4
by: barcaroller | last post by:
I was thinking of buying Scott Meyer's second book (More Effective C++) and noticed that it has not been updated since 1995 (unlike his other two famous books). Does anyone know (rumour or...
1
by: mahesh.kanakaraj | last post by:
Hi All, I have a confusion in finding the 'effective content' of a complex type definition in a XML Schema. I shall give you an example situation to clearly explain my problem. Let's have...
8
by: arnuld | last post by:
Hi all, I have come to a point where I can comprehend C++ code much better. I will finish C++ Primer 4/e within next few days. Right now I am feeling the need to have have coding standards when I...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.