Throwing exceptions from copy constructor

M

mihai

People say that is a bad technique to throw exception from
constructors; and that the solution would be to create a function
_create_ to initialize an object.

What about copy constructors? How can we avoid throwing exceptions? If
we already have an abject witch was initialized wit _create_ we will be
forced to call create in copy constructor and to throw exceptions from
it.

Have a nice day,
Mihai.
 
J

James Daughtry

People say that is a bad technique to throw exception from constructors
In an ideal world, constructors would never throw. In the real world,
that's not the case. Whether bad technique or not (I won't step on a
slippery slope like that), a non-trivial class will likely see a
situation where it could need to catch an exception caused by
construction of either a base class or one of the data members, and not
be able to reasonably handle it.

What would you do in that case? Complain that throwing from
constructors is bad style and do nothing? Sure, you could use a create
function to initialize the object, but if you call it in the
constructor and it throws, you're back to square one. That leaves
calling it outside of the constructor, which basically means that you
either require the client code to call it (a dangerous plan), or you
work out some ugly hack where create is only called for the first use
beyond the constructor.

What about default initialization? It's feasable that default
initialization could fail, and since that constitutes an exceptional
situation, the constructor could throw (bad style or not). So you find
yourself between a rock and a hard place with the ideal world and the
real world. And here's the bad The real world always wins.

This includes the copy constructor and in some cases the assignment
operator as well. I hate to say that you're SOL, but them's the breaks.
 
J

John Carson

mihai said:
People say that is a bad technique to throw exception from
constructors; and that the solution would be to create a function
_create_ to initialize an object.

What about copy constructors? How can we avoid throwing exceptions? If
we already have an abject witch was initialized wit _create_ we will
be forced to call create in copy constructor and to throw exceptions
from it.


I don't believe that well-informed people say constructors shouldn't throw.
They do say that *destructors* shouldn't throw.

The throwing of an exception by a constructor can cause a problem because it
means that the destructor is not called, which may mean that necessary
cleanup doesn't occur.

The standard way to handle this is to wrap anything in class A that needs to
be cleaned up in a class of its own (say, classes B, C and D) and then make
objects of those classes (say, b, c and d) members of A. The initialisation
of b, c and d can then occur in A's constructor (via the initialisation
list). If, say, the initialisation of d causes an exception, then b and c
will have been fully constructed (unlike the A object) and hence their
destructors will be called, even though the A object's constructor won't be.
This achieves the necessary cleanup.

The C++ FAQ on Exceptions and Error Handling has some useful stuff on this:

http://www.parashift.com/c++-faq-lite/exceptions.html
 
B

BigBrian

IMHO, that's silly ( saying that it's bad technique to throw from a
constructor ). What other mechanism is there to know if something goes
wrong with contructing an object? You can't return an error code from
the constructor, all you can do is throw an exception. Who said that
this is bad technique anyway?
 
A

Alf P. Steinbach

* BigBrian:
IMHO, that's silly ( saying that it's bad technique to throw from a
constructor ).
Yes.


What other mechanism is there to know if something goes
wrong with contructing an object?

An infinite number... ;-)

You can't return an error code from the constructor, all you can do is
throw an exception.

Nope.

class Silly
{
private:
bool iAmValid;

public:
Silly( int x, bool& ok ): iAmValid( x == 42 )
{
ok = iAmValid;
}
};

The reason why this _particular_ technique is bad is mainly that you risk
having invalid objects hanging around, so called ZOMBIE OBJECTS, which
necessitates much redundant checking of validity and leads to bugs.

Formally it's a kind of meta, second-level class invariant.

Worth noting: languages like Java and C# typically force you to have
zombie objects but in those languages the problem arises from the other end
of the object lifecycle, destruction. Because you don't have deterministic
destruction in those languages the programmer must call Dispose (or like)
methods explicitly, and the objects still exist afterwards. And so must
note for themselves that they're no longer valid, and so they're zombies
and can conceivably become zombies earlier on.

Also worth noting: handling of external resources in some cases require
zombie states. E.g., a file can become invalid at any time. An object
wrapping that file is then logically invalid for at least part of its
interface, a zombie object wrt. to the invalid parts of the interface.

Who said that [throwing an exception] is bad technique anyway?

Yes. Anyone worth listening to will tell the opposite. A clear but
limited discussion of why using exceptions in constructors, avoiding
zombie states, is given in Bjarne Stroustrup's TCPPPL appendix on
exception safety in the standard library, available as a PDF document
at <url: http://www.research.att.com/~bs/3rd_safe0.html>.
 
A

Amit

mihai said:
People say that is a bad technique to throw exception from
constructors; and that the solution would be to create a function
_create_ to initialize an object.

The so called bad technique is throwing exception from destructors, not
constructors.
What about copy constructors? How can we avoid throwing exceptions? If
we already have an abject witch was initialized wit _create_ we will be
forced to call create in copy constructor and to throw exceptions from
it.

There are many ways like turning your object into a zombie state. Read the
FAQ, it describes some of the techniques.
Of course, throwing exceptions from copy consturcotrs is what most would
recommend.
 
B

BigBrian

Yes, I guess somebody could do something like your Silly class, however
since it has problems I didn't consider this when I made my statement
about "what other mechanism exist (for notifying the client code that
an error has occured in a constructor)". In using the Silly class, the
calling code may not check the pass by reference value into this
constructor. Also, the silly class will need a bunch of if tests
throughout it's implementation.

Since you said there are infinitely many ways to provide this
mechanism, and the Silly class is clearly not the way to do it. Please
provide another method which is better than throwing an exception.

I understand that some objects need memebers to keep track of some sort
of state, and that state may at times be invalid. This is different
than error conditions which need to throw exceptions to notify the
calling code that something is wrong.
 
B

BigBrian

The so called bad technique is throwing exception from destructors, not
constructors.

I thought throwing an exception from a destructor was *MUCH* worse than
bad technique, it's plain outright WRONG. Aren't destructors REQUIRED
to NOT throw?
 
A

Alf P. Steinbach

* BigBrian:
Yes, I guess somebody could do something like your Silly class, however
since it has problems I didn't consider this when I made my statement
about "what other mechanism exist (for notifying the client code that
an error has occured in a constructor)". In using the Silly class, the
calling code may not check the pass by reference value into this
constructor. Also, the silly class will need a bunch of if tests
throughout it's implementation.

That's about right.

Since you said there are infinitely many ways to provide this
mechanism, and the Silly class is clearly not the way to do it. Please
provide another method which is better than throwing an exception.

You'll need to define "better" first.

But it's evident that you've misunderstood and skipped some points, so
there's no real need for that: do read my posting again.

I understand that some objects need memebers to keep track of some sort
of state, and that state may at times be invalid.

Yes, sort of.

This is different than error conditions which need to throw exceptions
to notify the calling code that something is wrong.

No, it's all about convenience, maintainability, productivity and so forth.
There's no absolute "need", just as there is no absolute "better". Those
are subjective, contextual judgements, not technical facts, although I
agree that concerning this issue you'd need very strong reasons for using
anything but exceptions and be able to justify it to someone competent.
 
A

Alf P. Steinbach

* BigBrian:
I thought throwing an exception from a destructor was *MUCH* worse than
bad technique, it's plain outright WRONG. Aren't destructors REQUIRED
to NOT throw?

No.

But a destructor for an object used in a standard collection is required
to not throw.

That's also the case for exception object destructors... ;-)
 
B

BigBrian

No.
But a destructor for an object used in a standard collection is required
to not throw.

I don't this this is strict enough. Most techniques for writing
exception safe code assumes that destructors to NOT throw.
 
B

BigBrian

You'll need to define "better" first.

It was implied that "better" meant without the stated problems with
your "Silly" class.
But it's evident that you've misunderstood and skipped some points,
so, there's no real need for that: do read my posting again.

You (arogantly) said there were infinate ways to do this, and now you
won't provide another mechanism?
No, it's all about convenience, maintainability, productivity and so forth.
There's no absolute "need", just as there is no absolute "better".

If the need to inform the user of a class that an error has occured is
a *requirement*, then there *is* an absolute need. This brings us back
to the issue... How else can you *guarentee* that the user of your
class knows (without a doubt) that an error has occured. Requiring the
user of your class to check a flag isn't good enough (due to the issues
that we already discoussed). What are the infinitely many other ways
to guarentte this is accomplish without throwing an exception?
 
A

Alf P. Steinbach

* BigBrian:
I don't this this is strict enough. Most techniques for writing
exception safe code assumes that destructors to NOT throw.

You asked: "Aren't destructors REQUIRED to NOT throw?".

You get an answer to that, not to something else that you even now aren't
telling what is.

Please don't use all caps, please don't quote out of context, please
don't add your own imagined context to responses (I at least am not a
telepath: I don't know what the heck you're talking about).
 
A

Alf P. Steinbach

* BigBrian:
It was implied that "better" meant without the stated problems with
your "Silly" class.


You (arogantly) said there were infinate ways to do this

The part "said there were infinate ways to do this" is a lie; the
"arogantly" is meaningless applied to something that hasn't happened.

Don't lie, don't insinuate.

You asked: "What other mechanism is there to know if something goes
wrong with contructing an object?"

You got the answer: "An infinite number... ;-)"

These include the Silly class way, abort, callback, global status
variable, factory with null-pointer result, even writing the result
to a file or sending an e-mail -- use your imagination.

and now you won't provide another mechanism?

If you can be more clear about the C++ question, I'll try to help you.

If the need to inform the user of a class that an error has occured is
a *requirement*, then there *is* an absolute need. This brings us back
to the issue... How else can you *guarentee* that the user of your
class knows (without a doubt) that an error has occured. Requiring the
user of your class to check a flag isn't good enough (due to the issues
that we already discoussed). What are the infinitely many other ways
to guarentte this is accomplish without throwing an exception?

There are _no_ ways that guarantee that.

In particular, an exception doesn't guarantee that; client code can
always nullify any guarantee you think you have.

Foo* p; try{ p = new Foo; } catch(...){}
// No guarantee here.

Hth.,

- Alf
 
C

Clark S. Cox III

I don't believe that well-informed people say constructors shouldn't
throw. They do say that *destructors* shouldn't throw.

The throwing of an exception by a constructor can cause a problem
because it means that the destructor is not called, which may mean that
necessary cleanup doesn't occur.

Just to clarify, the destructor of that class isn't called, but the
destructors of any already constructed superclasses are.
 
B

BigBrian

The part "said there were infinate ways to do this" is a lie; the
"arogantly" is meaningless applied to something that hasn't happened.

What! This isn't a lie. Here is a quote from one of your previous
message....

I wrote this....
And you wrote this...
 
B

BigBrian

In particular, an exception doesn't guarantee that; client code can
always nullify any guarantee you think you have.
Foo* p; try{ p = new Foo; } catch(...){}
// No guarantee here.

That's true. But in this case the user of the class has to
specifically add the above code to ignore the exception. In the case
of checking a return value, you have to specificially add code to check
it. It could be easy for the user of the class to forget to check for
an error. Thus, having to add code to say "I'm not intrested in your
error" is BETTER than writting code such that doing nothing saying same
thing ( as with an error flag ).
 
A

Alf P. Steinbach

* BigBrian:
What! This isn't a lie. Here is a quote from one of your previous
message....

I wrote this....

And you wrote this...

Ergo, you lied.

In addition to don't lie and don't insinuate:

Don't quote out of context.
 
A

Alf P. Steinbach

* BigBrian:
That's true. But in this case the user of the class has to
specifically add the above code to ignore the exception. In the case
of checking a return value, you have to specificially add code to check
it. It could be easy for the user of the class to forget to check for
an error. Thus, having to add code to say "I'm not intrested in your
error" is BETTER than writting code such that doing nothing saying same
thing ( as with an error flag ).

Add a "usually" and that will be generally true.

However there are many ways the client code can foul up, e.g.

int x = 1;
std::cout << x++ << "," << x << std::endl;
// We have Undefined Behavior, so no guarantee here:
Foo object;

No matter which method is employed one can only help the client code
programmer, one can not guarantee correct client code. And with that
perspective what constitutes the best help depends on the client code
programmer. And much else.

As an example of relevant purely technical consideration, in language
agnostic code such as the basic COM infrastructure it's not possible
to throw C++ exceptions out of the the interface the client code uses,
since the client code language may not understand them. So this is a
situation where exceptions are not clearly "better". For this example
exceptions are most probably "worse"... ;-)

At a higher level, with a good choice of error reporting mechanism C++
exceptions can be added on top, in a wrapper layer, for C++ client code.
The reverse, starting out with C++ exceptions and wrapping them, would
introduce a possible internal overhead for no gain. What's "better"
and "worse" is therefore highly contextual, not absolutes.
 
C

Calum Grant

mihai said:
People say that is a bad technique to throw exception from
constructors; and that the solution would be to create a function
_create_ to initialize an object.

Which people? Provided you know what you are doing, there is no problem.
What about copy constructors? How can we avoid throwing exceptions? If
we already have an abject witch was initialized wit _create_ we will be
forced to call create in copy constructor and to throw exceptions from
it.

It's more important to be exception-neutral. You can't avoid exceptions
(e.g. std::bad_alloc), and you can't in general control what other
classes decide to throw. The best you can hope to do is to recover
safely. Exception-neutrality means that you will safely pass through
exceptions to the caller, which is in general what you want.

Fantastic tools for exception safety are std::auto_ptr and swap. swap
does not throw. The assignment operator should (ideally) not leave the
object in a half-copied state in the face of an exception.

e.g. Here is an exception-neutral class. If allocation fails, or any of
the constructors throw, the class performs the correct clean-up.

class C
{
std::auto_ptr<X> x;
std::auto_ptr<Y> y;
public:
C(const C &c) : x(new X(*c.x)), y(new Y(*c.y))
{
}

C& operator=(const C &c)
{
std::auto_ptr<X> new_x(new X(*c.x));
std::auto_ptr<Y> new_y(new Y(*c.y));
x.swap(new_x);
y.swap(new_y);
return *this;
}
};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top