473,511 Members | 14,846 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Effective C++ by Scott Meyers

I right now reading this book.
And he is iterating some points I'm following since 1996, e.g.
exception safety.
But e.g. he is missing one of the major exception safety guidelines,
which is

Allocate only a single resource inside a constructor body (deallocate
in the matching destructor body).
Chain such classes into base-class/member-class relationships.
This way you are able to exploit the code generation features of the
compiler,
since you wont have to deal with partially constructed objects and
cleanup after an exception has been thrown.

I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

Feb 23 '07 #1
15 5899
Peter wrote:
I right now reading this book.
And he is iterating some points I'm following since 1996, e.g.
exception safety.
But e.g. he is missing one of the major exception safety guidelines,
which is

Allocate only a single resource inside a constructor body (deallocate
in the matching destructor body).
Chain such classes into base-class/member-class relationships.
This way you are able to exploit the code generation features of the
compiler,
since you wont have to deal with partially constructed objects and
cleanup after an exception has been thrown.

I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.
Effective C++ is not that modern a book is it, 10 years old according to
Amazon.

Your criticism is valid I guess, but Effective C++ is a beginners book,
and exception safety is an advanced topic.

It remains an exceptionally good book, taught me more about C++ than any
other single book I've read.

john
Feb 23 '07 #2

Peter wrote:
I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

and on page 138 he made a mistake in the order of constructor calls.
The correct order is:

bm1::constructor()
bm2::constructor()
Base::Base()
dm1::constructor()
dm2::constructor()
dm3::constructor()
Derived::Derived()

I left out the order of destructor calls in case of an exception.
But this is simple, as it is in reverse order.

This mistake did more damage than the book did good.

Feb 23 '07 #3
s5n
On Feb 23, 11:38 pm, "Peter" <pet...@xpedion.comwrote:
I right now reading this book.
And he is iterating some points I'm following since 1996, e.g.
exception safety.
But e.g. he is missing one of the major exception safety guidelines,
which is
....
I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.
Your points are valid, but don't forget how old that book is ("modern"
is not valid here, IMO). After writing that book Meyers released
Effective STL and is on the 3rd edition of More Effective C++. Not
*everything* could go into one book. :)

PS: i'm Scott Meyers' biggest fan. :)

Feb 24 '07 #4
On Feb 23, 6:10 pm, "Peter" <pet...@xpedion.comwrote:
Peter wrote:
I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

and on page 138 he made a mistake in the order of constructor calls.
The correct order is:

bm1::constructor()
bm2::constructor()
Base::Base()
dm1::constructor()
dm2::constructor()
dm3::constructor()
Derived::Derived()

I left out the order of destructor calls in case of an exception.
But this is simple, as it is in reverse order.

This mistake did more damage than the book did good.

It is not in reverse order. In the sequence above Derived() is invoked
first which invokes the other constructors. The only reason
Derived::Derived() is displayed last is because that ctor body is only
executed once the member constructions are completed.
The same applies to Base counterpart. bm1 and bm2 are constructed to
completion before the Base::Base() output is executed. The fact that
bm1 and bm2 constructors were invoked implies that the Base ctor
itself was invoked first.
Feb 24 '07 #5

"Salt_Peter" <pj*****@yahoo.comwrote in message
news:11*********************@z35g2000cwz.googlegro ups.com...
On Feb 23, 6:10 pm, "Peter" <pet...@xpedion.comwrote:
>Peter wrote:
I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

and on page 138 he made a mistake in the order of constructor calls.
The correct order is:

bm1::constructor()
bm2::constructor()
Base::Base()
dm1::constructor()
dm2::constructor()
dm3::constructor()
Derived::Derived()

I left out the order of destructor calls in case of an exception.
But this is simple, as it is in reverse order.

This mistake did more damage than the book did good.


It is not in reverse order. In the sequence above Derived() is invoked

the destruction is in reverse order of the constructors.
Only these destructors are called, for which the constructor was successful.
This is also true in case of the destruction is caused by an exception
thrown.
Do you claim that it is not so?

first which invokes the other constructors. The only reason
Derived::Derived() is displayed last is because that ctor body is only
executed once the member constructions are completed.
The same applies to Base counterpart. bm1 and bm2 are constructed to
completion before the Base::Base() output is executed. The fact that
bm1 and bm2 constructors were invoked implies that the Base ctor
itself was invoked first.

I'm not following.
Do you claim yet another construction order?
Do be explicit -- could you write down your construction order line by line?
But this does not matter -- I'm quite certain that I'm correct here.
I tested this in countless examples.

Feb 24 '07 #6
sks
"Peter" <pe****@xpedion.comwrote in message
news:11*********************@h3g2000cwc.googlegrou ps.com...
>I right now reading this book.
And he is iterating some points I'm following since 1996, e.g.
exception safety.
But e.g. he is missing one of the major exception safety guidelines,
which is

Allocate only a single resource inside a constructor body (deallocate
in the matching destructor body).
Chain such classes into base-class/member-class relationships.
This way you are able to exploit the code generation features of the
compiler,
since you wont have to deal with partially constructed objects and
cleanup after an exception has been thrown.

I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.
I didn't quite understand this but I would like to understand it. What did
you mean by "exploit the code generation features of the
compiler"?

Also, what is wrong with multiple resource allocations inside a constructor
body (as long as the matching destructor gets to deallocate them)?

Thanks.

Feb 24 '07 #7
* Peter:
>
"Salt_Peter" <pj*****@yahoo.comwrote in message
news:11*********************@z35g2000cwz.googlegro ups.com...
>On Feb 23, 6:10 pm, "Peter" <pet...@xpedion.comwrote:
>>Peter wrote:
I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

and on page 138 he made a mistake in the order of constructor calls.
The correct order is:

bm1::constructor()
bm2::constructor()
Base::Base()
dm1::constructor()
dm2::constructor()
dm3::constructor()
Derived::Derived()

I left out the order of destructor calls in case of an exception.
But this is simple, as it is in reverse order.

This mistake did more damage than the book did good.


It is not in reverse order. In the sequence above Derived() is invoked


the destruction is in reverse order of the constructors.
Only these destructors are called, for which the constructor was
successful.
This is also true in case of the destruction is caused by an exception
thrown.
Do you claim that it is not so?
Peter is talking about constructor calls, you're talking about finished
initializations (constructor body executions).

Those are different things.

For example, if Base and Derived are coded like
void say( char const s[] ) { std::cout << s << std::endl; }

int theAnswer( char const s[] ) { say( s ); return 42; }

struct Base
{
Base( int ) { say( "Base constructor" ); }
};

struct Derived
{
Derived(): Base( theAnswer( "Derived init list" ) )
{ say( "Derived constructor" ); }
};

int main() { Derived(); }

But this does not matter -- I'm quite certain that I'm correct here.
I tested this in countless examples.
Try the above.

--
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?
Feb 24 '07 #8

"sks" <sk*@yahoo.comwrote in message
news:LN*******************@newsfe14.lga...
I didn't quite understand this but I would like to understand it. What did
you mean by "exploit the code generation features of the
compiler"?

If you would have to perform an initialization of a complex object in C
you would have to perform checks if the initialization of a subobject was
successful.
In case of one initialization of some subobject fails you would have to call
the destructor of the already successful initialized subobjects.
You would have to maintain this order in the constructor and in the
destructor. Lets assume 3 parts A, B and C:
(0 return code stands for success, everything else for failure)

typedef struct
{
A sA;
B sB;
C sC;
} someStructure;

int initSomeStructure(someStructure *_p)
{ if (initA(&_p->sA))
return 1;
if (initB(&_p->sB))
{ destroyA(&_p->sA);
return 1;
}
if (initC(&_p->sC))
{ destroyB(&_p->sB);
destroyA(&_p->sA);
return 1;
}
return 0;
}
void destroySomeStructure(someStructure *_p)
{ destroyC(&_p->sC);
destroyB(&_p->sB);
destroyA(&_p->sA);
}
Usage of this code could look like this:

someStructure *p = malloc(sizeof*p);
if (!p)
{ printf("allocation of somestructure failed\n");
}
else
if (initSomeStructure(p))
{ free(p);
printf("Initialization of somestructure failed\n");

}
else
doSomething(p);

ok so far?

in C++ this would look like this:

struct SomeStructure
{ A m_sA;
B m_sB;
C m_sC;
SomeStructure(void)
{
}
};
Usage of this code would look like this:

SomeStructure *p;
try
{ p = new SomeStructure;
} catch (const std::exception &_r)
{ cout << "Initialization or allocation of somestructure failed with
msg: " << _r.why() << "\n";
}
p->doSomething();
The C++ compiler is generating all this code for you (initializaing the
subobjects and dealing with failure if initialization of some subobject
fails).
I only used a heap-allocated object to show that the compiler generates a
call to delete if the constructor fails.
Notice that you enter the same catch-block independ of whether the
constructor fails or whether new fails.

Also, what is wrong with multiple resource allocations inside a
constructor
body (as long as the matching destructor gets to deallocate them)?

if you allocate multiple resources in a single constructor-body
(
e.g. not as subobjects but e.g. pointers.
Same applies if you wrap multiple C-style resources initializations inside a
single class instead of one class for one C-style resource
):
struct A
{ B *m_pB;
C *m_pC;
D *m_pD;
A(void)
{ m_pB = createB();
try
{ m_pC = createC();
} catch (...)
{ delete m_pB;
throw;
}
try
{ m_pD = createD();
} catch (...)
{ delete m_pC;
delete m_pB;
throw;
}
}
~A(void)
{ delete m_pD;
delete m_pC;
delete m_pB:
}
};

Same applies if your creation functions are C-style error code returning
functions.
You would have to perform cleanup duty yourself.

It is better to use sub-objects:

struct A
{ std::auto_ptr<Bm_sB;
std::auto_ptr<Cm_sC;
std::auto_ptr<Dm_sD;
A(void)
: m_sB(createB()),
m_sC(createC()),
m_sD(createD())
{
}
}
Here the compiler generates the code which destroys the already successfully
constructed subobjects
if construction of some subobject fails.
And you don't need to code the destructor at all.

(
std::auto_ptr is an exception to the rule that you should undo in the
destructor what you did in the constructor.
using std::auto_ptr you undo in the destructor what you do just before
calling the constructor.
This is ok, since the constructor of std::auto_ptr never throws.
)
Using C++ Exception Handling it is finally possible to use constructors for
fallible resource allocation.
Write one class for every type of resource allocation you have to perform.
Then chain such classes into base-class or member-class relationships.
Of course you will have to know (and exploit) the order of construction of
base-objects/member-objects.

Feb 24 '07 #9
On Feb 23, 4:47 pm, John Harrison <john_androni...@hotmail.comwrote:
Peter wrote:
I right now reading this book.
And he is iterating some points I'm following since 1996, e.g.
exception safety.
But e.g. he is missing one of the major exception safety guidelines,
which is
Allocate only a single resource inside a constructor body (deallocate
in the matching destructor body).
Chain such classes into base-class/member-class relationships.
This way you are able to exploit the code generation features of the
compiler,
since you wont have to deal with partially constructed objects and
cleanup after an exception has been thrown.
I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

Effective C++ is not that modern a book is it, 10 years old according to
Amazon.

Your criticism is valid I guess, but Effective C++ is a beginners book,
and exception safety is an advanced topic.

It remains an exceptionally good book, taught me more about C++ than any
other single book I've read.

john
can you suggest a good book for advanced topic in c++? e.g. the
exception safety that you mention?
Feb 24 '07 #10
yi*****@gmail.com wrote:
On Feb 23, 4:47 pm, John Harrison <john_androni...@hotmail.comwrote:
>>Peter wrote:
>>>I right now reading this book.
And he is iterating some points I'm following since 1996, e.g.
exception safety.
But e.g. he is missing one of the major exception safety guidelines,
which is
>>>Allocate only a single resource inside a constructor body (deallocate
in the matching destructor body).
Chain such classes into base-class/member-class relationships.
This way you are able to exploit the code generation features of the
compiler,
since you wont have to deal with partially constructed objects and
cleanup after an exception has been thrown.
>>>I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

Effective C++ is not that modern a book is it, 10 years old according to
Amazon.

Your criticism is valid I guess, but Effective C++ is a beginners book,
and exception safety is an advanced topic.

It remains an exceptionally good book, taught me more about C++ than any
other single book I've read.

john


can you suggest a good book for advanced topic in c++? e.g. the
exception safety that you mention?

There's a series of books that grew out of the guru of the week column
(http://www.gotw.ca/gotw/), the first is called Exceptional C++ by Herb
Sutter.

Personally I didn't like the style much, but the material covered is good.

john
Feb 24 '07 #11
On Feb 23, 7:47 pm, John Harrison <john_androni...@hotmail.comwrote:
Peter wrote:
I right now reading this book.
And he is iterating some points I'm following since 1996, e.g.
exception safety.
But e.g. he is missing one of the major exception safety guidelines,
which is
Allocate only a single resource inside a constructor body (deallocate
in the matching destructor body).
Chain such classes into base-class/member-class relationships.
This way you are able to exploit the code generation features of the
compiler,
since you wont have to deal with partially constructed objects and
cleanup after an exception has been thrown.
I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

Effective C++ is not that modern a book is it, 10 years old according to
Amazon.

Your criticism is valid I guess, but Effective C++ is a beginners book,
and exception safety is an advanced topic.

It remains an exceptionally good book, taught me more about C++ than any
other single book I've read.

john
I can surely say I only learned C++ properly after I read Scott
Meyers.
I agree completely with john

(and I only learned templates properly after Alexandrescu...)

Diego

Feb 26 '07 #12
On Feb 23, 6:10 pm, "Peter" <pet...@xpedion.comwrote:
Peter wrote:
I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.

and on page 138 he made a mistake in the order of constructor calls.
The correct order is:
<snip>
This mistake did more damage than the book did good.
Really? That seems like a slight overreaction.
Feb 26 '07 #13

<da***********@fastmail.fmwrote in message
news:11********************@v33g2000cwv.googlegrou ps.com...
>This mistake did more damage than the book did good.

Really? That seems like a slight overreaction.

I happen to consider the order of construction of a nontrival class
as one of the most important things to know about C++.
A lot of things can be done during construction of an object,
which somebody who does not know about this, may do inside some
init-function.
I consider usage of an init-function to be pre-C++-Exception-Handling-Style.

Feb 27 '07 #14
Peter wrote:
I consider usage of an init-function to be
pre-C++-Exception-Handling-Style.
A class should be easy to use, both for production clients and test cases.
So a class that has the option to construct with links to other obese
classes should also have the option to construct minimally.

Yes, adept use of fat constructors does demonstrate modern C++
understandings. That's no excuse to make every constructor fat.

--
Phlip
http://www.greencheese.us/ZeekLand <-- NOT a blog!!!
Feb 27 '07 #15
On Feb 24, 4:10 am, John Harrison <john_androni...@hotmail.comwrote:
ying...@gmail.com wrote:
On Feb 23, 4:47 pm, John Harrison <john_androni...@hotmail.comwrote:
>Peter wrote:
>>I right now reading this book.
And he is iterating some points I'm following since 1996, e.g.
exception safety.
But e.g. he is missing one of the major exception safety guidelines,
which is
>>Allocate only a single resource inside a constructor body (deallocate
in the matching destructor body).
Chain such classes into base-class/member-class relationships.
This way you are able to exploit the code generation features of the
compiler,
since you wont have to deal with partially constructed objects and
cleanup after an exception has been thrown.
>>I was thinking that this rule is already in broad usage and should be
part of any modern book on C++.
>Effective C++ is not that modern a book is it, 10 years old according to
Amazon.
>Your criticism is valid I guess, but Effective C++ is a beginners book,
and exception safety is an advanced topic.
>It remains an exceptionally good book, taught me more about C++ than any
other single book I've read.
>john
can you suggest a good book for advanced topic in c++? e.g. the
exception safety that you mention?

There's a series of books that grew out of the guru of the week column
(http://www.gotw.ca/gotw/), the first is called Exceptional C++ by Herb
Sutter.

Personally I didn't like the style much, but the material covered is good.

john
these books are good, but their style is too tiresome. I never could
finish this books

Effective C++, More Effective C++, Effective STL and Modern C++ Design
serve well as reference guides because they are well organized

the organization of gotw books is too confusing. I think a clipping or
a reedition may be of great help in order to get the valuable material
of Herb Sutter (exception safety is his best approach, imho)

Diego

Feb 27 '07 #16

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

Similar topics

5
5763
by: Matt Priest | last post by:
I am trying to learn more about how to effectively mix low-level C code with C++. I am having trouble finding resources/papers/books that aren't in one or the other camp exclusively. Can anyone...
25
7523
by: Matthias | last post by:
Hi, I am just reading that book by Scott Meyers. In Item 4 Meyers suggests to always use empty() instead of size() when probing for emptyness of STL containers. His reasoning is that size()...
4
1965
by: John | last post by:
I am looking for a good Lock class implementation that has barely been implemented in Effective STL of Myers (Item 12). Any pointers? Is there an implementation that is good for both OpenMP and...
4
2408
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...
44
3818
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...
15
1978
by: vikram_p_nayak | last post by:
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...
3
1552
by: Zongjun Qi | last post by:
Hey, In the book <Effective C++>, the author provides an example to prove why we need "pass by reference". I redoed the example, and found something interesting. The codes are:...
7
3077
by: eric | last post by:
hello i'm confused by an example in the book "Effective C++ Third Edition" and would be grateful for some help. here's the code: class Person { public: Person(); virtual ~Person(); // see...
4
1882
by: jfwfmt | last post by:
Please pardon my ignorance. I'm writing a C++ STL program after not writing code for 7 years, I'm trying to invoke key_word.inc() using an iterator for a set containing key_word_T. The following...
0
7252
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7153
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7371
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7517
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5676
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5077
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3230
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3218
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
791
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.