473,396 Members | 1,866 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

Throwing exceptions from copy constructor

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.

Jul 23 '05 #1
21 4359
>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 news: 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.

Jul 23 '05 #2
"mihai" <Mi*********@gmail.com> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.com
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

--
John Carson

Jul 23 '05 #3
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?

Jul 23 '05 #4
* 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: 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?
Jul 23 '05 #5

"mihai" <Mi*********@gmail.com> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.com...
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.

Have a nice day,
Mihai.

Jul 23 '05 #6
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.

Jul 23 '05 #7
>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?

Jul 23 '05 #8
* 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: 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?
Jul 23 '05 #9
* 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?


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... ;-)

--
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?
Jul 23 '05 #10
>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.

Jul 23 '05 #11
>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?

Jul 23 '05 #12
* 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.


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: 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?
Jul 23 '05 #13
* 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


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.

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?


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

--
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?
Jul 23 '05 #14
On 2005-06-02 09:04:34 -0400, "John Carson"
<jc****************@netspace.net.au> said:
"mihai" <Mi*********@gmail.com> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.com
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.


Just to clarify, the destructor of that class isn't called, but the
destructors of any already constructed superclasses are.
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

--
Clark S. Cox, III
cl*******@gmail.com

Jul 23 '05 #15
>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....
What other mechanism is there to know if something goes
wrong with contructing an object?


And you wrote this...An infinite number... ;-)


Jul 23 '05 #16
>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 ).

Jul 23 '05 #17
* 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....
What other mechanism is there to know if something goes
wrong with contructing an object?


And you wrote this...
An infinite number... ;-)


Ergo, you lied.

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

Don't quote out of context.

--
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?
Jul 23 '05 #18
* 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 ).


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.

--
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?
Jul 23 '05 #19
mihai wrote:
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;
}
};
Have a nice day,
Mihai.

Jul 23 '05 #20
* Calum Grant:

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))
{
}
For others who read this, a subtle point: this works because there's a
sequence point between each pair of initializer in the initialization list.
In a an ordinary function call it's generally not safe to have more than one
'new' in the arguments. One cure is then to wrap the allocations in
functions so that the compiler cannot choose to first allocate all objects'
memory and only then call the constructors.

Btw., there should really be some way to construct a C object... ;-)

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;
}
Typo: you meant

std::swap( x, new_x );
std::swap( y, new_y );

(std::auto_ptr has no swap member function).
};


--
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?
Jul 23 '05 #21
"John Carson" <jc****************@netspace.net.au> wrote in message
news:d7***********@otis.netspace.net.au

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.


Typo here:

"even though the A object's constructor won't be"

should be

"even though the A object's *destructor* won't be"

--
John Carson
Jul 23 '05 #22

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

Similar topics

5
by: Mark Oueis | last post by:
I've been struggling with this question for a while. What is better design? To design functions to return error codes when an error occures, or to have them throw exceptions. If you chose the...
11
by: mangesh | last post by:
I read , FAQ : 17.4] How should I handle resources if my constructors may throw exceptions? Above faq says that use smart pointer in construcors . Because if exception is thrown from constructor...
15
by: Sek | last post by:
Gurus, I am wondering whether it is right to throw an exception from a Property of an object. To get into it further, is it okay to throw exception during 'get' operation? I was searching...
40
by: Sek | last post by:
Is it appropriate to throw exception from a constructor? Thats the only way i could think of to denote the failure of constructor, wherein i am invoking couple of other classes to initialise the...
6
by: Marvin Barley | last post by:
I have a class that throws exceptions in new initializer, and a static array of objects of this type. When something is wrong in initialization, CGI program crashes miserably. Debugging shows...
8
by: Ruben | last post by:
Hello I'm struggling with the throw and catch exception system. As I understood it, when you throw an error, that the stack is searched for a matching catch, but I'm having difficult finding...
21
by: Chris M. Thomasson | last post by:
Is it every appropriate to throw in a dtor? I am thinking about a simple example of a wrapper around a POSIX file... ________________________________________________________________________ class...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
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
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
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
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
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,...

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.