Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Are throwing default constructors bad style, and if so, why?

165 views
Skip to first unread message

Andrei Alexandrescu

unread,
Sep 17, 2008, 7:28:54 AM9/17/08
to
I have the intuition that defining a type with a throwing default
constructor has bad style all over it. However, I can't seem to pinpoint
a few strong reasons to back up my belief. So I wanted to discuss it
here - do you think defining a throwing default constructor is a bad
idea, and if so, why? If not, what would be some good examples?

A default constructor can be argument-less or with all-defaulted arguments:

struct S1 { S1() { ... } };
struct S2 { S2(int x = 42) { ... } };


Andrei


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

wasti...@gmx.net

unread,
Sep 17, 2008, 3:58:41 PM9/17/08
to
On 17 Sep., 13:28, Andrei Alexandrescu <SeeWebsiteForEm...@erdani.org>
wrote:

> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it.

Absolutely not. If, like me, you're not a fan of two-stage
construction, constructors must throw whenever they cannot fully
initialize the object, arguments or not. If they acquire any resource
that can fail - memory, a mutex, ... - the constructor can throw.

Take, for example, a C++ wrapper around an OS mutex. When you create
it, there's typically no reason to pass any arguments. Maybe some
configuration, but it will have defaults. If the class then fails to
acquire an OS mutex, what should it do? Sit there in an unusable
state, waiting for someone to call lock() just so it can throw? Or
should it throw immediately?

Mathias Gaunard

unread,
Sep 17, 2008, 4:02:25 PM9/17/08
to
On 17 sep, 13:28, Andrei Alexandrescu <SeeWebsiteForEm...@erdani.org>
wrote:

> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it. However, I can't seem to pinpoint
> a few strong reasons to back up my belief. So I wanted to discuss it
> here - do you think defining a throwing default constructor is a bad
> idea, and if so, why? If not, what would be some good examples?

A likely case when you have a constructor that doesn't throw is
because your object doesn't need to own any resource but its own
memory.
Anoter likely case is because it doesn't acquire any resource in the
constructor; it sets the object to an empty state, for example (empty
std::function, null smart pointer, ...).

I personally think that empty states, which are more and more common,
are an unsafe way to program (and also add overhead). So my opinion is
that there should not be a non-throwing default constructor that
doesn't fully initialize the object and acquire all the resources it
needs. That often means no default constructor.

Alex

unread,
Sep 17, 2008, 6:28:59 PM9/17/08
to
On Sep 17, 7:28 am, Andrei Alexandrescu

<SeeWebsiteForEm...@erdani.org> wrote:
> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it. However, I can't seem to pinpoint
> a few strong reasons to back up my belief. So I wanted to discuss it
> here - do you think defining a throwing default constructor is a bad
> idea, and if so, why?

Can be a bad idea because it typically indicates latent coupling which
is worse than ordinary, obvious coupling.
If default constructor throws, something has gone awry in the object
without user passing any information to it. This means that the object
is either (a) internally ill-conceived or (b) depends on something
external which is not immediately obvious.

Coupling is sometimes unavoidable and in those cases, it should be as
obvious as possible - best indicated at compile time.
For example, there's no use for a socket without it's peer on the
other side - coupling is an intrinsic part of the functionality, hence
unavoidable.
According to RAII principle, connect should be done at create time,
which means user should be forced to provide the IP:port to the
constructor and the default constructor should be private.

> If not, what would be some good examples?

Let's say that an object uses temporary file or allocates memory from
heap. For user's convenience, we provide RAII creation/deletion of the
file/memory. Default constructor throws if temporary file can not be
created or memory allocated. The behavior, of course, should be
properly documented, but in this case, IMO, convenience trumps the
perils of non-obvious coupling.

The bottom line would be:

If class is not coupled with any resource external to it, throwing in
default constructor is a design or logic flaw.
If class is coupled with a named resource (file, socket,
database, ...), there should be no default constructor (and,
consequently, no throwing from default constructor).
If class is coupled with a generic resource (temporary file, heap
memory, ...) that can be acquired without user supplying any
information about it, then default constructor should throw.

My $.002

Alex

Martin Bonner

unread,
Sep 17, 2008, 6:28:55 PM9/17/08
to
On Sep 17, 12:28 pm, Andrei Alexandrescu

<SeeWebsiteForEm...@erdani.org> wrote:
> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it. However, I can't seem to pinpoint
> a few strong reasons to back up my belief. So I wanted to discuss it
> here - do you think defining a throwing default constructor is a bad
> idea, and if so, why? If not, what would be some good examples?
>

Consider an object that represents a an off-screen image buffer. If
you run out of memory on the graphics card, you have to signal the
failure to create the object. The best way to do that is via an
exception. The constructor might well have default arguments for
extent and depth of the buffer. There's no obvious need for a name or
similar. I can't see the problem.

analizer

unread,
Sep 17, 2008, 6:28:59 PM9/17/08
to
On Sep 17, 3:28 pm, Andrei Alexandrescu

<SeeWebsiteForEm...@erdani.org> wrote:
> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it. However, I can't seem to pinpoint
> a few strong reasons to back up my belief. So I wanted to discuss it
> here - do you think defining a throwing default constructor is a bad
> idea, and if so, why? If not, what would be some good examples?


IMHO, throwing c'tor is a good practice if this c'tor performs any non-
trivial initializations (like socket connect, file read, attach to
pipe or message queue created by other process, etc.), this is only
way to report an error during object construction. You can say that
class should provide something like initialize() function for such
operations that will return result code for operation, but this
solution have following disadvantages:
1. Non-transparent dependency: you'll need to call this function each
time you creates such objects, of course you can provide factory that
will return pointer to new object or NULL if initialize() function
have failed, but Occam's Razor learns us that this solution is bad.
2. You won't be able to declare members filled with initialize() as
const's. For example, it is much better when you able to initialize
const socket in the members initialization list in c'tor.

Main reason to use throwing c'tors is ability to graceful handling of
static variables initializations (for example, for singletons), if
exception have been thrown in c'tor then static variable won't be
marked as initialized and initialization will be repeated during the
next function call. This way you can easily handle singletons
initialization failures (I can imagine situation when we should check
some connection singleton initialization when client connection
singleton have been created before server one, and we should wait a
bit).

So, I see no problems in throwing c'tors usage. I agree, exceptions
are slow, but if c'tor have failed this means something really bad
happened and performance is not a high priority here.

Dmitry

Nevin :-] Liber

unread,
Sep 17, 2008, 6:28:58 PM9/17/08
to
In article <K7BHn...@beaver.cs.washington.edu>,
Andrei Alexandrescu <SeeWebsit...@erdani.org> wrote:

> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it. However, I can't seem to pinpoint
> a few strong reasons to back up my belief. So I wanted to discuss it
> here - do you think defining a throwing default constructor is a bad
> idea, and if so, why? If not, what would be some good examples?

I think it is bad mainly because it goes against people's expectations.

I know it certainly went against my expectations when I found out the
default constructor for std::deque (under gcc 3.3.3; I haven't looked to
see if that has changed in later STL implementations) can throw.

If the default constructor of an object can throw, I suddenly have to
"be careful" when using that object as a member in another object, since
the "default constructor can throw" has a ripple effect.

Using std::deque for an example, if I have

struct Something
{
//...
std::deque<int> di;
};

In order to make the default constructor of Something non-throwing, I'd
have to write it as:

struct Something
{
Something() {}

Something(Something const& that)
: pdi(that.pdi ? new std::deque<int>(*pdi) : 0)
{}

//...

boost::scoped_ptr< std::deque<int> > pdi;
};

and the associated complexity of pointer semantics (an extra heap
allocation, test for NULL pointer on access, custom copy constructor,
etc.) instead of the object directly.

--
Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> 773 961-1620

Alberto Ganesh Barbati

unread,
Sep 17, 2008, 6:28:55 PM9/17/08
to
Andrei Alexandrescu ha scritto:

> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it. However, I can't seem to pinpoint
> a few strong reasons to back up my belief. So I wanted to discuss it
> here - do you think defining a throwing default constructor is a bad
> idea, and if so, why? If not, what would be some good examples?

Good question. Given that the constructor has no parameters to validate,
the decision to throw or not must depend on some external state.
Accessing external state in the form of global variables may be frowned
upon regardless of the issue at hand, but there is one external state
that can't be easily avoided: memory. If the default constructed object
needs to allocate any amount of memory and there is not enough, then
it's correct, IMHO, for the constructor to throw.

Just my opinion,

Ganesh

Marsh Ray

unread,
Sep 17, 2008, 6:29:00 PM9/17/08
to
On Sep 17, 6:28 am, Andrei Alexandrescu

<SeeWebsiteForEm...@erdani.org> wrote:
> do you think defining a throwing default constructor is a bad
> idea, and if so, why?

Well, if any constructor (default or otherwise) can't complete its
work properly, it has to throw, right?

Since the default ctor generally isn't taking any args in the usual
sense, it's either going to:
1. never throw
2. always throw, or
3. throw or not based on "ambient" state or other runtime events

Cases 1 and 2 seem to be uninteresting for our discussion.

For case 3, I can think of some sources of ambient state that could
affect successful construction:

1. global data
I suspect the general problems with global data may be the root of
your intuition.

2. file-scope static data
Similar to global data, but IMHO not really as severe.

Some run-time events:

1. Resource exhaustion
Surely it's reasonable for a default constructor occasionally to call
'new'?

2. An exception thrown from or failure code returned from code that's
not under your control, maybe not even written in C++.
In my work, I'm constantly writing classes to manage OS-handle-based
objects and and other API calls that expect to be called in pairs. For
example, creating a Win32 critical section object generally doesn't
require any parameters to the constructor, but has been known to fail
at runtime (perhaps this is just another example of resource
exhaustion though?)

Perhaps a better example: Before I can use sockets under Win32, I have
to call a 'WSAStartup()' function, which is supposed to be paired with
an eventual 'WSACleanup()' call. My habit is to use a ctor/dtor for
this kind of thing. The startup call (historically anyway) will
succeed or fail based on a comaprison of the level of functionality I
request (which is generally compile-time constant) vs. patches and
updates to the end-user's OS. My constructor for this class needs no
arguments, but it's success cannot be guaranteed in practice.

So I think finding you've coded a throwing default ctor might be a
good signal to double-check the design, but it's also something that's
going to arise naturally in real-world programs utilizing RAII to the
fullest, most general sense.

But highly-general platform-neutral library code that doesn't have any
dependencies outside of the current standard (i.e., the kind of stuff
you like to write :-), I can't think of many cases (new/bad_alloc)
where it would makes much sense.

- Marsh

David Abrahams

unread,
Sep 17, 2008, 6:28:58 PM9/17/08
to
On Sep 17, 4:28 am, Andrei Alexandrescu

<SeeWebsiteForEm...@erdani.org> wrote:
> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it. However, I can't seem to pinpoint
> a few strong reasons to back up my belief. So I wanted to discuss it
> here - do you think defining a throwing default constructor is a bad
> idea, and if so, why?

I don't know why this idea that any constructor shouldn't throw keeps
raising its ugly head. I keep killing it off, and it keeps coming
back. Constructors and exceptions have a beautiful relationship, as
throwing constructors allow the establishment of strong class
invariants. There's certainly nothing inherently different between

X();

and

X(5);

There is only one angle I can think of that could lead to a plausible
argument against throwing default ctors. Most movable types need to
have a resourceless "moved-from" state in their invariants. Resource
allocation being the primary source of exceptions, one can usually
eliminate throws from the default ctor by having it produce the "moved-
from" state without technically weakening the invariant. Since
nonthrowing operations can be used in more liberally than throwing
ones, such a design theoretically improves usability.

However, I don't buy it. The lifetime of "moved-from" objects is
sufficiently short (usually just a prelude to destruction) that
limiting the resourceless state to objects that have actually been
moved-from and not allowing people to easily construct such objects
can still be useful in increasing clarity, maintainability, and
security. Remember, class invariants aren't 100% bulletproof anyway,
as they can be violated during construction and destruction (not to
mention mutation). Being able to say that "except for moved-from
objects, I always know that I own my resources" is very powerful.

--
Dave Abrahams
Boostpro Computing
http://boostpro.com

blargg

unread,
Sep 18, 2008, 4:23:26 PM9/18/08
to
In article
<ec1fa5b1-dac7-4111...@a1g2000hsb.googlegroups.com>,
wasti...@gmx.net wrote:

> On 17 Sep., 13:28, Andrei Alexandrescu <SeeWebsiteForEm...@erdani.org>
> wrote:
> > I have the intuition that defining a type with a throwing default
> > constructor has bad style all over it.
>
> Absolutely not. If, like me, you're not a fan of two-stage
> construction, constructors must throw whenever they cannot fully
> initialize the object, arguments or not. If they acquire any resource
> that can fail - memory, a mutex, ... - the constructor can throw.
>
> Take, for example, a C++ wrapper around an OS mutex. When you create
> it, there's typically no reason to pass any arguments. Maybe some
> configuration, but it will have defaults. If the class then fails to
> acquire an OS mutex, what should it do? Sit there in an unusable
> state, waiting for someone to call lock() just so it can throw? Or
> should it throw immediately?

Or a similar variant: wait to acquire the mutex until the first member
function call that uses it, causing the exception as before. Allocating
resources in the constructor allows member functions to rely on them
being already allocated, rather than checking each and allocating if not
already allocated. It also allows the user to handle resource allocation
exceptions ahead of time, eliminating the possibility of those
exceptions from member function calls. In many cases, that can allow
member functions to throw no exceptions, simplifying user code.

If the user really wants to delay acquisition, perhaps until first use,
he should delay constructing the object. That's something to be
implemented once in a class template, or just implemented via a smart
pointer and new. The class template could even automatically create the
object the first time -> is used on it. This approach doesn't burden
those users who don't need delayed acquisition (construction).

Dave Harris

unread,
Sep 18, 2008, 4:22:49 PM9/18/08
to
> I have the intuition that defining a type with a throwing default
> constructor has bad style all over it. However, I can't seem to
> pinpoint
> a few strong reasons to back up my belief. So I wanted to discuss it
> here - do you think defining a throwing default constructor is a bad
> idea, and if so, why? If not, what would be some good examples?

It seems fine to me, to the point that I wonder if I've misunderstood the
question. At the risk of stating the obvious, it's good to throw if it
can't allocate a resource it needs to satisfy its class invariant.

struct FixedBuffer {
size sz;
char *pData;
FixedBuffer( int sz=256 ) : sz( sz ), pData( new char[sz] ) {
}
//...
};

I don't see anything wrong with a constructor like this. You can't return
error status from a constructor, and we shouldn't expect clients to
remember to use two-phase construction or to check a status flag after
construction. This is what RAII is all about - making a strong class
invariant or throwing if you can't.

If you mean a constructor that /always/ throws, then it's bad style in
that it's a bit pointless calling it. A class like:

struct FixedBuffer {
size sz;
char *pData;
FixedBuffer( int sz ) : sz( sz ), pData( new char[sz] ) {
}
FixedBuffer() {
throw "You forgot to pass the size!";
}
//...
};

would be better off making the default constructor private so the mistake
is detected at compile-time.

-- Dave Harris, Nottingham, UK.

Jonathan Jones

unread,
Sep 18, 2008, 4:22:32 PM9/18/08
to

> On 17 Sep., 13:28, Andrei Alexandrescu <SeeWebsiteForEm...@erdani.org>
> wrote:
> > I have the intuition that defining a type with a throwing default
> > constructor has bad style all over it.
>
> Absolutely not. If, like me, you're not a fan of two-stage
> construction, constructors must throw whenever they cannot fully
> initialize the object, arguments or not. If they acquire any resource
> that can fail - memory, a mutex, ... - the constructor can throw.
>
> Take, for example, a C++ wrapper around an OS mutex. When you create
> it, there's typically no reason to pass any arguments. Maybe some
> configuration, but it will have defaults. If the class then fails to
> acquire an OS mutex, what should it do? Sit there in an unusable
> state, waiting for someone to call lock() just so it can throw? Or
> should it throw immediately?

What would the default constructor _usefully_ do that might lead to an
error requiring a throw? In your example, you could easily refactor
the code to only manipulate the OS mutex through a non-default
constructor, leaving the default constructor to perform simple, safe
initialization. In my opinion, this seems like better style, but
perhaps I'm overlooking something.

Andre Kaufmann

unread,
Sep 18, 2008, 5:28:53 PM9/18/08
to
analizer wrote:
> On Sep 17, 3:28 pm, Andrei Alexandrescu
> <SeeWebsiteForEm...@erdani.org> wrote:
>
> So, I see no problems in throwing c'tors usage. I agree, exceptions

I think there are perhaps some minor problems:

a) A global object, which throws, will cause the application to
teminate / crash, without being able to handle the error.

b) If one uses function pairs to be called in the
constructor / destructor and the constructor throws,
the destructor won't be called.

If RAII objects are used to handle this there shouldn't be a problem,
but the developer has to be always aware of the
destructor not being called - it's simply another pitfall.

c) How many developers expect constructors to throw ?

I tend to initialize and use resources as late as possible.
Therefore I don't have commonly the need to allocate resources and
handle errors in the constructor anyways.

> [...]

Joshua...@gmail.com

unread,
Sep 20, 2008, 2:09:46 AM9/20/08
to
On Sep 18, 1:22 pm, Jonathan Jones <hid...@this.is.invalid> wrote:
> In article
> <ec1fa5b1-dac7-4111-adb2-c847c8af8...@a1g2000hsb.googlegroups.com>,

>
>
>
> wasti.r...@gmx.net wrote:
> > On 17 Sep., 13:28, Andrei Alexandrescu <SeeWebsiteForEm...@erdani.org>
> > wrote:
> > > I have the intuition that defining a type with a throwing default
> > > constructor has bad style all over it.
>
> > Absolutely not. If, like me, you're not a fan of two-stage
> > construction, constructors must throw whenever they cannot fully
> > initialize the object, arguments or not. If they acquire any resource
> > that can fail - memory, a mutex, ... - the constructor can throw.
>
> > Take, for example, a C++ wrapper around an OS mutex. When you create
> > it, there's typically no reason to pass any arguments. Maybe some
> > configuration, but it will have defaults. If the class then fails to
> > acquire an OS mutex, what should it do? Sit there in an unusable
> > state, waiting for someone to call lock() just so it can throw? Or
> > should it throw immediately?
>
> What would the default constructor _usefully_ do that might lead to an
> error requiring a throw? In your example, you could easily refactor
> the code to only manipulate the OS mutex through a non-default
> constructor, leaving the default constructor to perform simple, safe
> initialization. In my opinion, this seems like better style, but
> perhaps I'm overlooking something.

Why? What do you gain by having a "zombie" / uninitialized state?

Basically, it's the argument of exception-using code vs C-style code.
I like using exceptions for when I cannot acquire a resource.

You no longer have to construct the object then initialize it. Thus
you no longer have concerns about zombie objects. you also have much
less error handling code (you don't have the scattered "If failed to
initialize, return error"). This leads to less code, easier to read
code, and easier to verify correctness of code.

You will also have faster code. The extra function calls to initialize
the object and the extra if statements to return early on a failure
will perform slower than exceptions. The extra if statements will
raise instruction cache misses by adding instructions with the common
case code, whereas any decent compiler will put the exception handlers
in a far far away place in memory, increasing instruction locality for
the normal successful path.

Mathias Gaunard

unread,
Sep 20, 2008, 2:15:06 AM9/20/08
to
On 18 sep, 23:28, Andre Kaufmann <akfmn...@t-online.de> wrote:

> c) How many developers expect constructors to throw ?

Any one that ever heard about RAII, exceptions, STL or modern C++?
(pick one)


> I tend to initialize and use resources as late as possible.
> Therefore I don't have commonly the need to allocate resources and
> handle errors in the constructor anyways.

Then you're really missing the whole point of constructors, I guess.
They're made to initialize. If you want delayed initialization, just
delay construction.
Also, you're paying an extra overhead, since your object can always be
in a "non-initialized-yet" state, which means your invariant really
isn't what it ought to be.

Erik Wikström

unread,
Sep 20, 2008, 2:12:21 AM9/20/08
to

The problem with the constructor to perform a safe initialisation is
that it will leave the object in a constructed but unusable state, which
means that each call to a member function might potentially throw, or at
the very least they have to check for the unusable state when using the
object.

Another point to consider is the case when it simply does not make sense
to pass any parameters.

--
Erik Wikström

Maciej Sobczak

unread,
Sep 20, 2008, 2:10:27 AM9/20/08
to
On 18 Wrz, 22:23, blargg <blargg....@gishpuppy.com> wrote:

> Or a similar variant: wait to acquire the mutex until the first member
> function call that uses it

How would you do that in a thread-safe way?

Note: the thread-safety in this context means that when two threads
attempt to call such operation at the same time, only one should
initialize the mutex, but both should use it. I have never seen it
done properly and I have seen serious bugs in Very Important Programs
exactly because of this.

Coming back to the original subject, there are only two alternatives:
- use constructors and allow them to throw, or
- don't use constructors at all and rely on separate init functions
where there is a choice on how to report errors (by exceptions or by
error codes)

I don't claim that any of these two is better than the other because
there are justified use cases for both, but using constructors and
disallowing them to throw always leads to broken designs on a higher
level.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

The C++ Database Access Library: soci.sourceforge.net

blargg

unread,
Sep 20, 2008, 2:12:46 AM9/20/08
to
In article <gatuku$bo2$00$1...@news.t-online.com>,

Andre Kaufmann <akfm...@t-online.de> wrote:
> analizer wrote:
> > On Sep 17, 3:28 pm, Andrei Alexandrescu
> > <SeeWebsiteForEm...@erdani.org> wrote:
> >
> > So, I see no problems in throwing c'tors usage. I agree, exceptions
>
> I think there are perhaps some minor problems:
>
> a) A global object, which throws, will cause the application to
> teminate / crash, without being able to handle the error.

Then make the global object a smart pointer and don't allocate the
object until it's first used. I consider global non-trivial objects bad
style, because of this issue.

> b) If one uses function pairs to be called in the
> constructor / destructor and the constructor throws,
> the destructor won't be called.
>
> If RAII objects are used to handle this there shouldn't be a problem,
> but the developer has to be always aware of the
> destructor not being called - it's simply another pitfall.

But one has this problem regardless of whether the default constructor
of any other classes throws, unless you're arguing that NO constructors
should throw.

> c) How many developers expect constructors to throw ?

Shouldn't a developer generally expect everything to throw, and only
write code that can't handle exceptions in the cases where none are
thrown and handling them is too costly/difficult? If things are written
correctly, in most cases handling exceptions doesn't impose much of a
burden.

> I tend to initialize and use resources as late as possible.
> Therefore I don't have commonly the need to allocate resources and
> handle errors in the constructor anyways.

You're not getting the full benefit of constructors. They are there to
establish an object's invariant. The more stringent the invariant, the
fewer possibilities member functions have to deal with.

analizer

unread,
Sep 20, 2008, 2:28:07 AM9/20/08
to
On Sep 19, 1:28 am, Andre Kaufmann <akfmn...@t-online.de> wrote:
> a) A global object, which throws, will cause the application to
> teminate / crash, without being able to handle the error.

What about to use singletons instead of "global objects"? Global
objects cause too many pitfalls such as initialization and linkage
orders etc. For singletons you can handle exceptions in c'tors
gracefully. Also this will allow to delay object initialization, it
will be initialized when it will be used first time.

>
> b) If one uses function pairs to be called in the
> constructor / destructor and the constructor throws,
> the destructor won't be called.
>
> If RAII objects are used to handle this there shouldn't be a problem,
> but the developer has to be always aware of the
> destructor not being called - it's simply another pitfall.

True. The only cure here is to use objects that will perform self
uninitialization or use guard objects those will perform
uninitialization of objects those have no d'tors.

> c) How many developers expect constructors to throw ?

All (ideally). If class method (including c'tor) throws exception,
then this should be reflected in code comments in header file. Anyone
who uses the class method should learn how this method works, for
example by reading comments to this method.

Andrei Alexandrescu

unread,
Sep 20, 2008, 2:23:01 AM9/20/08
to
Thanks to all who responded to my inquiry. There's been a great deal of
insightful answers and examples given, such as:

1. Mutex initialization. It turns out that only initialization (not
acquisition!) of a mutex could fail. For example pthread_mutex_init
could fail (see
http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_init.html).
Interestingly, InitializeCriticalSection returns void (see
http://msdn.microsoft.com/en-us/library/ms683472(VS.85).aspx) but may
fail by throwing a structured exception on pre-Vista Windae.

2. An image buffer would require dynamic allocation in its constructor
for proper functioning, which might fail.

3. More generally, objects of which state depends on globals and
singletons might as well throw an exception in their default constructor.

Along the way, considerations regarding "moved-from" states, two-stage
construction (blech), and lazy initialization were made. Neat.

I asked the question because I'm coming from a slightly unusual angle.
I've been using a garbage-collected environment for a while. When a GC
is in the equation *together* with deterministic destruction,
Interesting Things(TM) happen. One of them is that it's a great idea to
separate teardown (destruction) from deallocation. For example:

Foo * p = new Foo(...);
...
delete p;

In a GC environment, it makes a lot of sense if the delete statement
only invokes Foo's destructor against *p and then... leaves the object
alone in a "valid but non-resource-consuming" state.

Such an approach is not foreign to many on this group; there's been many
a discussion about what was descriptively called "zombie" object states.

The advantage of separating teardown from deallocation is that there are
no more dangling pointers, and consequently even incorrect programs
could achieve predictable, reproducible, and consequently debuggable
behavior. That way you get to use GC for what it's best at (recycling
memory) and deterministic teardown for what it's best at (timely release
of resources). In fact I'd go as far as saying that I think separating
teardown from deallocation an essential ingredient in successfully
marrying deterministic teardown with garbage collection. Other schemes
could be conceived, and I've thought of a few, but at least those I
could imagine lead to a mésalliance at most.

Once we accept the reality of "destroyed but not deallocated" objects,
we need to define that state appropriately. That state claims no more
resources than the bits of Foo alone, and must be detected by all member
functions of the object such that they have defined behavior for that state.

A genuinely distinct state could be defined. A reasonable decision is to
define that state as the default constructed state. Such a decision may
not always be perfect, but it has some advantages:

a) For many types, the default constructor does construct an impersonal,
empty, aloof object that does no more than compare equal to all other
default-constructed objects. Save for collecting information from the
environment, a default-constructed object does not have any
parameterization to make it "different".

b) All member functions need to take care of the "zombie" state anyway,
and often they also need to take care of the default-constructed state,
so merging the two can simplify things.

c) The rule is easy to explain and remember. Introducing a new zombie
state defined on a per-case basis only further adds to the complications
of defining types.

d) Non-throwing default constructors occasionally facilitate writing
algorithms. For example, in Hoare's partition it's convenient to store
the pivot in a local temporary. The temporary is default-constructed and
then only swapped around. In other words, non-throwing default
constructors allow writing "conservative" algorithms on collections that
do not create any new value, but do use temporary memory to shuffle
values around.

There are disadvantages too, for example it becomes impossible to
distinguish a legit default-constructed object from one that has had a
life and kicked the bucket. For example in the mutex case it may make
sense to define a default-constructed mutex one on which initialization
did succeed, and a zombie one a mutex that is obliterated with an
illegal bit pattern. (A more portable solution would need to add a bool
to the object state.)

I'd be interesting in hearing further opinions on how garbage collection
interacts with defining object states.


Andrei

Gerhard Menzl

unread,
Sep 20, 2008, 2:28:40 AM9/20/08
to
Nevin :-] Liber wrote on throwing default constructors:

> I think it is bad mainly because it goes against people's
> expectations.

Against which people's expectations? An experienced C++ programmer
should expect any non-trivial operation to throw unless it is explicitly
documented that it doesn't.

> If the default constructor of an object can throw, I suddenly have to
> "be careful" when using that object as a member in another object,
> since the "default constructor can throw" has a ripple effect.

This is the very nature of exceptions. Except for low-level, C-style
code, all code needs to be exception safe. In modern C++, the
possibility of an exception being thrown is the norm, and its absence
is, well, the exception.

> Using std::deque for an example, if I have
>
> struct Something
> {
> //...
> std::deque<int> di;
> };
>
> In order to make the default constructor of Something non-throwing,
> I'd have to write it as:
>
> struct Something
> {
> Something() {}
>
> Something(Something const& that)
> : pdi(that.pdi ? new std::deque<int>(*pdi) : 0)
> {}
>
> //...
>
> boost::scoped_ptr< std::deque<int> > pdi;
> };
>
> and the associated complexity of pointer semantics (an extra heap
> allocation, test for NULL pointer on access, custom copy constructor,
> etc.) instead of the object directly.

What's the advantage of a non-throwing default constructor, and of
deferring the construction of the deque? As soon as you want to use
Something, you will trigger the delayed operation, and then you have to
be prepared for exceptions anyway.

--
Gerhard Menzl

Non-spammers may respond to my email address, which is composed of my
full name, separated by a dot, followed by at, followed by "fwz",
followed by a dot, followed by "aero".

Andre Kaufmann

unread,
Sep 20, 2008, 9:38:41 PM9/20/08
to
blargg wrote:
> [...]

>>> So, I see no problems in throwing c'tors usage. I agree, exceptions
>> I think there are perhaps some minor problems:
>>
>> a) A global object, which throws, will cause the application to
>> teminate / crash, without being able to handle the error.
>
> Then make the global object a smart pointer and don't allocate the
> object until it's first used. I consider global non-trivial objects bad
> style, because of this issue.

I agree. But there is still much code around simply using global objects
which use resources - e.g. a global object which wraps a mutex.
It's valid C++ even if it's perhaps not "good style - modern C++" and it
isn't that easy to write multi threaded safe global objects / singletons
anyways.

It would be fine if C++ would delay initialization of global objects
anyways, till they are used first time. But that is another story.

>> b) If one uses function pairs to be called in the
>> constructor / destructor and the constructor throws,
>> the destructor won't be called.
>>
>> If RAII objects are used to handle this there shouldn't be a problem,
>> but the developer has to be always aware of the
>> destructor not being called - it's simply another pitfall.
>
> But one has this problem regardless of whether the default constructor
> of any other classes throws, unless you're arguing that NO constructors
> should throw.

Yes. It's only a simple pitfall - I think quite too simple to run into.
E.g.:

class Foo
{
public:
Foo () { Lock (); }
~Foo() { Unlock(); }
};

No problem with that. But when I modify the object.

class Foo
{
public:
Foo () { Lock (); AcquireResources(); // might throw }
~Foo() { Unlock(); }
};

And AcquireResources() will throw an exception Unlock won't be called
anymore.
Yes - in a perfect C++ world Lock() Unlock() would have been called by a
RAII object. But I've seen too much code like that, without using RAII
and it's IMHO quite too easy to oversee that pitfall, even for
experienced C++ developers (which not necessarily have written that code)


>> c) How many developers expect constructors to throw ?
>
> Shouldn't a developer generally expect everything to throw, and only
> write code that can't handle exceptions in the cases where none are
> thrown and handling them is too costly/difficult? If things are written
> correctly, in most cases handling exceptions doesn't impose much of a
> burden.

Yes - agreed a developer should expect any function / constructor to
throw an exception. I only listened some problems, which might occur
when a constructor throws (if used in bad style code).
Perhaps code will be still safe, because the exceptions are handled
correctly, because the code is exception safe anyways.
But there might be a small significant difference in control flow, if
the developer doesn't always think about that each line of code could
fail by throwing an exception - even constructors.


I only have the impression, that many mediocre developers (perhaps even
experienced ones) when asked which of the following code lines may throw
an exception:

a) MyObject a[100];
b) foo(MyObject()); // Foo doesn't throw
c) MyObject a;
d) object++;
e) HandleResources();

would not say (without thinking it over) that each code line could throw
an exception and would tend to say e) might throw.


Surely a C++ expert wouldn't have to look at the code and say each code
line of code might throw an exception ;-).

>> I tend to initialize and use resources as late as possible.
>> Therefore I don't have commonly the need to allocate resources and
>> handle errors in the constructor anyways.
>
> You're not getting the full benefit of constructors. They are there to
> establish an object's invariant. The more stringent the invariant, the
> fewer possibilities member functions have to deal with.

But why would it be (generally) a benefit to allocate resources in the
constructor ?
(That doesn't mean that I don't initialize the state of the object
itself in the constructor)
I too allocate resources in objects constructors, where I have to and
where it would be too tedious to check the objects state in each member
function - e.g in lightweight objects.

Andre

Eugene Gershnik

unread,
Sep 20, 2008, 9:38:33 PM9/20/08
to
On Sep 19, 11:23 pm, Andrei Alexandrescu

<SeeWebsiteForEm...@erdani.org> wrote:
>
> The advantage of separating teardown from deallocation is that there are
> no more dangling pointers,

They can still happen if they point to external resources.

> and consequently even incorrect programs
> could achieve predictable, reproducible, and consequently debuggable
> behavior.

This assumes that the zombie state and the entire state machine it
brings to every object are implemented correctly. Which from my
experience with GC languages is as hard to do as to correctly use
manual memory management. If there is a mistake in zombification or
checking for a zombie-ness you might still have crashes or other forms
of UB when accessing an object in this state. Also note that usually
zombie state will be a rarely used and debugged one. It is also often
only accessed under specific timing conditions which makes the
'reproducible' argument weak.

> Once we accept the reality of "destroyed but not deallocated" objects,
> we need to define that state appropriately. That state claims no more
> resources than the bits of Foo alone, and must be detected by all member
> functions of the object such that they have defined behavior for that state.

Yep. And this is hard to get right (and maintain being right).

--
Eugene

Andre Kaufmann

unread,
Sep 20, 2008, 9:36:35 PM9/20/08
to
Joshua...@gmail.com wrote:
> On Sep 18, 1:22 pm, Jonathan Jones <hid...@this.is.invalid> wrote:


> [...]


>> What would the default constructor _usefully_ do that might lead to an
>> error requiring a throw? In your example, you could easily refactor
>> the code to only manipulate the OS mutex through a non-default
>> constructor, leaving the default constructor to perform simple, safe
>> initialization. In my opinion, this seems like better style, but
>> perhaps I'm overlooking something.
>

> [...]


> You will also have faster code. The extra function calls to initialize
> the object and the extra if statements to return early on a failure
> will perform slower than exceptions.

Depending on how good the compiler optimizes. Normally using exceptions
adds another overhead for each function to keep track of created objects
(exception stack), which might significantly increase the code size
(too). There might be additional code added for each throw statement used.

So I wouldn't bet on the code which uses exceptions to be really faster.

> [...]

Andre

Mathias Gaunard

unread,
Sep 20, 2008, 9:34:25 PM9/20/08
to
On 20 sep, 08:23, Andrei Alexandrescu <SeeWebsiteForEm...@erdani.org>
wrote:

> The advantage of separating teardown from deallocation is that there are
> no more dangling pointers, and consequently even incorrect programs
> could achieve predictable, reproducible, and consequently debuggable
> behavior. That way you get to use GC for what it's best at (recycling
> memory) and deterministic teardown for what it's best at (timely release
> of resources). In fact I'd go as far as saying that I think separating
> teardown from deallocation an essential ingredient in successfully
> marrying deterministic teardown with garbage collection. Other schemes
> could be conceived, and I've thought of a few, but at least those I
> could imagine lead to a mésalliance at most.

GC can be nothing but a memory allocation/deallocation strategy for
RAII.
For example, upon destruction of a dynamically allocated object, one
could choose to call the destructor, but not free the memory.
Better, if you think of mark & sweep for example, you could replace
the deallocation by marking the said object as dead. So GC only needs
to handle sweep, no reachability analysis is needed at all.

The object doesn't exist anymore, there is no need for any additional
"zombie" state within it. That state is available within the memory
block which has been marked as dead anyway.

Note that with this approach, though, you do not avoid dangling
pointers or whatever. It's just an optimization strategy for memory
management, correctness is still attained through RAII.

Andre Kaufmann

unread,
Sep 20, 2008, 9:36:38 PM9/20/08
to
Mathias Gaunard wrote:
> On 18 sep, 23:28, Andre Kaufmann <akfmn...@t-online.de> wrote:
>
>> c) How many developers expect constructors to throw ?
>
> Any one that ever heard about RAII, exceptions, STL or modern C++?
> (pick one)

So all code is written in modern C++ and all existing C++ code is 100%
exception safe ? At least my experience is that the world isn't perfect
and RAII and "modern C++" isn't that common as it should be.

>> I tend to initialize and use resources as late as possible.
>> Therefore I don't have commonly the need to allocate resources and
>> handle errors in the constructor anyways.
>
> Then you're really missing the whole point of constructors, I guess.
> They're made to initialize. If you want delayed initialization, just
> delay construction.

Perhaps there's a difference between initialization of variables /
states and the initialization / acquisition of resources ?

> Also, you're paying an extra overhead, since your object can always be
> in a "non-initialized-yet" state, which means your invariant really
> isn't what it ought to be.

Examples:

- The default constructor of an vector for example doesn't IIRC allocate
any memory.
- Why should an object which handles bitmaps allocate any bitmap
resources if it doesn't know the dimensions of the bitmap anyway ?

Andre

Dave Harris

unread,
Sep 20, 2008, 9:34:32 PM9/20/08
to
SeeWebsit...@erdani.org (Andrei Alexandrescu) wrote (abridged):

> Once we accept the reality of "destroyed but not deallocated"
> objects, we need to define that state appropriately. That
> state claims no more resources than the bits of Foo alone, and
> must be detected by all member functions of the object such that
> they have defined behavior for that state.

By "the bits of Foo alone", do you mean just sizeof(Foo)? Because I'd
have thought the zombie object would often be allowed to own other memory,
which would also be collected by the GC in due course rather than as part
of deterministic teardown. Releasing non-memory resources is often
necessary for correctness, and releasing memory resources is often (but
not always) just an optimisation (with GC).

Which means it makes sense (from a GC perspective) to make that owned
memory part of the class invariant and to allocate it in the constructor.
Which might fail and throw.


> A genuinely distinct state could be defined. A reasonable decision
> is to define that state as the default constructed state.

If an object does have a valid zombie state, then I agree it's a good
rule of thumb if the object can be constructed in that state. Although
usually it makes sense for the default constructor to do that, I am not
yet sure it's a universal rule.

For me one of the main ways a default constructor is special is that it
is used for arrays. So the question is whether code like:
Foo array[100];

should create 100 zombie Foos, or 100 usable ones. The people who don't
expect code to throw would presumably want zombies, but I can imagine
situations where having to follow this with a loop:

Foo array[100];
for (int i = 0; i < 100; ++i)
array[i].initialise();

would be inelegant. And of course the opposite, eg where an array of N
items is allocated in advance but only the first M items are in use and
need to consume resources.

I don't think we can have absolute rules here, only guidelines.

-- Dave Harris, Nottingham, UK.

--

Erik Wikström

unread,
Sep 20, 2008, 9:32:53 PM9/20/08
to
On 2008-09-20 08:23, Andrei Alexandrescu wrote:

> I asked the question because I'm coming from a slightly unusual angle.
> I've been using a garbage-collected environment for a while. When a GC
> is in the equation *together* with deterministic destruction,
> Interesting Things(TM) happen. One of them is that it's a great idea to
> separate teardown (destruction) from deallocation. For example:
>
> Foo * p = new Foo(...);
> ...
> delete p;
>
> In a GC environment, it makes a lot of sense if the delete statement
> only invokes Foo's destructor against *p and then... leaves the object
> alone in a "valid but non-resource-consuming" state.
>
> Such an approach is not foreign to many on this group; there's been many
> a discussion about what was descriptively called "zombie" object states.
>
> The advantage of separating teardown from deallocation is that there are
> no more dangling pointers, and consequently even incorrect programs
> could achieve predictable, reproducible, and consequently debuggable
> behavior. That way you get to use GC for what it's best at (recycling
> memory) and deterministic teardown for what it's best at (timely release
> of resources). In fact I'd go as far as saying that I think separating
> teardown from deallocation an essential ingredient in successfully
> marrying deterministic teardown with garbage collection. Other schemes
> could be conceived, and I've thought of a few, but at least those I
> could imagine lead to a mésalliance at most.

This really is not my area of expertise, but I fail to see how leaving
the object in an zombie-state will improve when it comes to dangling
pointers. After all, sooner or later the GC will come and collect the
used memory and it might be used by some other object. So at most you
manage to hide the fact that you are using an invalid pointer a bit longer.

I do agree that separating teardown from deallocation makes sense,
perhaps not only in a GC (I can imagine batching deallocations with
without a GC) but I still think that after the destructor has run the
object should be considered no longer existent.

--
Erik Wikström

Andrei Alexandrescu

unread,
Sep 20, 2008, 9:47:58 PM9/20/08
to

I'm highly surprised by this behavior of deque. I'd have hoped that STL
containers at least abide to a no-throwing-default-construction mantra.
The way that that deque is defined, it's impossible to conservatively
acquire the contents of one deque.

(When I say "conservative" in this context I mean it as an analogy to
"energy conservative" in physics, i.e. no effort is expended. Swapping
and moving are conservative, copying is not.)

For example, IMHO move construction should never, ever throw. I think
this is an immutable ideal, just like the energy conservation principle
is in physics. We start with a number of objects. We end with the same
number of objects, just in a different place. There shouldn't be at any
point any "effort" expended on allocating extra memory, aside from the
"friction" of moving bits around. Making the default constructor throw
makes moving via swap (the only move available for C++03)
non-conservative and consequently wasteful and potentially incorrect (if
peer code expects moving cannot engender exceptions). It is reasonable
to think that an object could embed a deque inside and, without risking
an exception, "absorbs" another deque.

Heck, if deque's constructor attempts to allocate memory (and
consequently throw), you can't even use the swap trick to ensure you
have completely emptied a deque. So picture the irony: _emptying_ a
deque via the swap trick could _throw_. This is a correctness issue that
I guess simply rules the swap trick out as a method of emptying a
container in C++03.


Andrei

--

David Abrahams

unread,
Sep 20, 2008, 9:53:03 PM9/20/08
to

on Thu Sep 18 2008, Andre Kaufmann <akfmnews-AT-t-online.de> wrote:

> a) A global object, which throws, will cause the application to
> teminate / crash, without being able to handle the error.

So it's OK for this global object to throw

Foo x(5);

but not this one?

Foo x;

If so, why?

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Andre Kaufmann

unread,
Sep 20, 2008, 9:58:54 PM9/20/08
to
analizer wrote:
> On Sep 19, 1:28 am, Andre Kaufmann <akfmn...@t-online.de> wrote:
>> a) A global object, which throws, will cause the application to
>> teminate / crash, without being able to handle the error.
>
> What about to use singletons instead of "global objects"? Global
> objects cause too many pitfalls such as initialization and linkage
> orders etc. For singletons you can handle exceptions in c'tors
> gracefully. Also this will allow to delay object initialization, it
> will be initialized when it will be used first time.

Agreed. But there's too much code around simply using global objects and
singletons aren't that simple to handle in a multi threaded application.
I too don't use (complex) global objects, but unfortunately the world
isn't perfect ;-).

> [...]

>> c) How many developers expect constructors to throw ?
>
> All (ideally). If class method (including c'tor) throws exception,
> then this should be reflected in code comments in header file. Anyone
> who uses the class method should learn how this method works, for
> example by reading comments to this method.

O.k. I agree, in modern C++ it's no problem to throw an exception in the
constructor and I would agree too that it's also a good style in modern
C++ to throw an exception in the constructor.

I only listed some problems, which might occur in old style, but still
common C++ code ;-)

> Dmitry

Andre

Mathias Gaunard

unread,
Sep 21, 2008, 5:35:30 PM9/21/08
to
On 21 sep, 03:36, Andre Kaufmann <akfmn...@t-online.de> wrote:

> So I wouldn't bet on the code which uses exceptions to be really faster.

Exceptions are faster than if/else branches and return codes, there
are no tests or branching.
That's the whole point of the Itanium Exception ABI; they're zero-
overhead (or quasi-zero, some might say)

Yes, it generates bigger code, however.

Andrei Alexandrescu

unread,
Sep 21, 2008, 5:35:14 PM9/21/08
to

I walk along the same reasoning myself. A default-constructed, empty
container should not automatically assume I'll need to fill it right
away and be eager to preallocate (and refuse to even come into existence
if it can't right then and there)! This is quite clearly a design mistake.

But the example with the mutex makes a very strong counter-argument,
particularly since safely initializing lazily a mutex is not an easy
task itself. On the other hand, I don't feel that if I just create a
mutex (e.g. as a member) the mutex should assume my purpose is to
acquire it and therefore eagerly allocate resources...


Andrei

Andrei Alexandrescu

unread,
Sep 21, 2008, 5:42:07 PM9/21/08
to

I also agree it's fine and good style to throw from a constructor. I
only wonder (without being strongly convinced) whether throwing from the
constructor of an un-customized object is good.

Construction with parameters is a statement of intent. I, $DEITY, am
creating this object with specific parameters that give it personality
and make it "special", end expect the object to take shape according to
those parameters. If not possible, an exception is in order.

Construction without parameters seems in many cases to me a
"personalization to come later" statement, an as-of-yet-unexpressed
intent to make use of that object in accordance to its type, and also a
desire to keep options open and therefore preserve the object in an
inert state. Since often objects don't have all relevant data to fill
their subobjects during construction, I think it's only natural to
initialize them parameterlessly (and expect to not throw), to fill them
later on. Examples include all sorts of serialization scenarios
(including reading from databases, files, sockets, and so on). Also, if
you sorted a vector<deque<int> > and wanted to swap the pivot into a
temporary, is it reasonable for that temporary's non-argument
initialization to throw?


Andrei

Andrei Alexandrescu

unread,
Sep 21, 2008, 5:47:09 PM9/21/08
to
Dave Harris wrote:
> SeeWebsit...@erdani.org (Andrei Alexandrescu) wrote (abridged):
>> Once we accept the reality of "destroyed but not deallocated"
>> objects, we need to define that state appropriately. That
>> state claims no more resources than the bits of Foo alone, and
>> must be detected by all member functions of the object such that
>> they have defined behavior for that state.
>
> By "the bits of Foo alone", do you mean just sizeof(Foo)? Because I'd
> have thought the zombie object would often be allowed to own other memory,
> which would also be collected by the GC in due course rather than as part
> of deterministic teardown. Releasing non-memory resources is often
> necessary for correctness, and releasing memory resources is often (but
> not always) just an optimisation (with GC).

That's an interesting take. I was thinking that the destructor of an
object should set to null all pointer members. That way, even if there
are still dangling pointers referring to the zombie object, the other
subobjects reachable through the object can be freed properly (assuming
of course there are no dangling pointers to _them_!)

> Which means it makes sense (from a GC perspective) to make that owned
> memory part of the class invariant and to allocate it in the constructor.
> Which might fail and throw.

Within that approach, I agree.

>> A genuinely distinct state could be defined. A reasonable decision
>> is to define that state as the default constructed state.
>
> If an object does have a valid zombie state, then I agree it's a good
> rule of thumb if the object can be constructed in that state. Although
> usually it makes sense for the default constructor to do that, I am not
> yet sure it's a universal rule.

Me neither. I only see it as a sort of a compromise between simplicity
and correctness.

> For me one of the main ways a default constructor is special is that it
> is used for arrays. So the question is whether code like:
> Foo array[100];
>
> should create 100 zombie Foos, or 100 usable ones. The people who don't
> expect code to throw would presumably want zombies, but I can imagine
> situations where having to follow this with a loop:
>
> Foo array[100];
> for (int i = 0; i < 100; ++i)
> array[i].initialise();
>
> would be inelegant. And of course the opposite, eg where an array of N
> items is allocated in advance but only the first M items are in use and
> need to consume resources.
>
> I don't think we can have absolute rules here, only guidelines.

Well I'm glad you brought that up too. The thing with
default-constructed arrays that could throw has also irked me for quite
a while. There's all that protocol for constructing arrays that led in
part to the "destructors can't throw" mantra. So many people have taken
that mantra non-critically, it has effectively petrified into a dogma.
But IMHO destructors should throw if they smell anything fishy. I'll
keep that for a different post.

Note that I don't see a need for the loop initializing elements of the
array. In my view, default-constructed objects should be usable out of
the box.


Andrei

Andrei Alexandrescu

unread,
Sep 21, 2008, 5:47:01 PM9/21/08
to
Eugene Gershnik wrote:
> On Sep 19, 11:23 pm, Andrei Alexandrescu
> <SeeWebsiteForEm...@erdani.org> wrote:
>> The advantage of separating teardown from deallocation is that there are
>> no more dangling pointers,
>
> They can still happen if they point to external resources.
>
>> and consequently even incorrect programs
>> could achieve predictable, reproducible, and consequently debuggable
>> behavior.
>
> This assumes that the zombie state and the entire state machine it
> brings to every object are implemented correctly. Which from my
> experience with GC languages is as hard to do as to correctly use
> manual memory management. If there is a mistake in zombification or
> checking for a zombie-ness you might still have crashes or other forms
> of UB when accessing an object in this state. Also note that usually
> zombie state will be a rarely used and debugged one. It is also often
> only accessed under specific timing conditions which makes the
> 'reproducible' argument weak.

Au contraire, the fact that zombie state is the default-constructed
state makes it very easy to both attain and check. It only requires
careful writing of the destructor (it would be nicer still if the
compiler planted the appropriate code itself). Also, since all member
functions must check for the default-constructed state to start with,
they won't have any trouble in dealing with zombie objects.

>> Once we accept the reality of "destroyed but not deallocated" objects,
>> we need to define that state appropriately. That state claims no more
>> resources than the bits of Foo alone, and must be detected by all member
>> functions of the object such that they have defined behavior for that state.
>
> Yep. And this is hard to get right (and maintain being right).

Well if you implemented std::vector, wouldn't you check for the empty
vector (begin == end == store_end) anyway? Would you argue that empty
states bring trouble to implementing std::vector?


Andrei

Andrei Alexandrescu

unread,
Sep 21, 2008, 5:44:04 PM9/21/08
to

The GC recycles memory when by definition the program cannot reach it.
This excludes a number of oddities such as forging pointers, but by and
large it can be used as an axiom.

Andrei

--

Joshua...@gmail.com

unread,
Sep 21, 2008, 5:45:37 PM9/21/08
to
On Sep 20, 6:36 pm, Andre Kaufmann <akfmn...@t-online.de> wrote:

> JoshuaMaur...@gmail.com wrote:
> > On Sep 18, 1:22 pm, Jonathan Jones <hid...@this.is.invalid> wrote:
> > [...]
> >> What would the default constructor _usefully_ do that might lead to an
> >> error requiring a throw? In your example, you could easily refactor
> >> the code to only manipulate the OS mutex through a non-default
> >> constructor, leaving the default constructor to perform simple, safe
> >> initialization. In my opinion, this seems like better style, but
> >> perhaps I'm overlooking something.
>
> > [...]
> > You will also have faster code. The extra function calls to initialize
> > the object and the extra if statements to return early on a failure
> > will perform slower than exceptions.
>
> Depending on how good the compiler optimizes. Normally using exceptions
> adds another overhead for each function to keep track of created objects
> (exception stack), which might significantly increase the code size
> (too). There might be additional code added for each throw statement used.
>
> So I wouldn't bet on the code which uses exceptions to be really faster.

This is the way they used to be implemented. For example, Visual
Studios 2003 implements it that way.

On any good compiler, during normal course of operation, there is
absolutely no additional work. When an exception is thrown, it goes to
a global lookup table based on the current program counter value. This
table is built at compile time. Each entry points to a block of code
to properly tear down the currently constructed portion of the stack
frame, then pass control to the next compiler-made exception handler
of the containing stack frame, or to a user's catch block.

Now, arguably, it won't result in terribly faster code in most uses.
We're just talking about a couple less if statements, but that's a
couple less if statements on the normal execution path than what we
had before. Less actual machine instructions run, and higher
instruction cache hit rates.

Andre Kaufmann

unread,
Sep 21, 2008, 5:48:18 PM9/21/08
to
David Abrahams wrote:
> on Thu Sep 18 2008, Andre Kaufmann <akfmnews-AT-t-online.de> wrote:
>
>> a) A global object, which throws, will cause the application to
>> teminate / crash, without being able to handle the error.
>
> So it's OK for this global object to throw
>
> Foo x(5);
>
> but not this one?
>
> Foo x;
>
> If so, why?

I think the effect is the same, regardless which constructor is called -
if it throws an exception.
And therefore no constructor of global instantiated objects should throw
exceptions - regardless if it's a bad style to use global objects or
not, since AFAIK there's no portable possibility for an application to
handle such exceptions - at least not if the code can't be changed.

Andre

--

Mathias Gaunard

unread,
Sep 21, 2008, 5:58:56 PM9/21/08
to
On 21 sep, 03:36, Andre Kaufmann <akfmn...@t-online.de> wrote:

> So all code is written in modern C++ and all existing C++ code is 100%
> exception safe ? At least my experience is that the world isn't perfect
> and RAII and "modern C++" isn't that common as it should be.

So you propose that instead of fixing it, we keep in mind that most
code is ill-designed and that broken idioms should still be supported
by newly-designed code?


> Perhaps there's a difference between initialization of variables /
> states and the initialization / acquisition of resources ?

Well, when resource acquisition is initialization, there is none.


> Examples:
>
> - The default constructor of an vector for example doesn't IIRC allocate
> any memory.

A vector is a sequence of elements. Having zero element is a perfectly
valid state.
The default constructor of vector makes it have zero element.
Allocating memory is not required for the object to function properly
then.
It may still allocate memory however (for future insertions) the
standard doesn't prevent it.


> - Why should an object which handles bitmaps allocate any bitmap
> resources if it doesn't know the dimensions of the bitmap anyway ?

The object probably should be given that kind of information as
arguments to its constructor.

Mathias Gaunard

unread,
Sep 21, 2008, 5:58:56 PM9/21/08
to