5

I'm wondering how to stop/cancel the creation of an object, risen by new(). Maybe if some preconditions fail and the object isn't needed.

  • Check before new?
  • Check within constructor, returning null or something special, don't know how to handle ...
  • Check after new was successful and object is alive. Call a member function myObj->Init(). And destroy object if this fails?
Benjamin
  • 1,143
  • 1
  • 14
  • 29
  • 3
    See this also: http://stackoverflow.com/questions/810839/throwing-exceptions-from-constructors – Naveen Sep 29 '11 at 10:37
  • 2
    Don't focus in new(). Your (clean) way to control these situations is in the constructor, and this will be called also without a new statement: "Widget myWidget;" or "Widget myWidget(this_variable, that_variable)" will call the constructor without using "new". – Daniel Daranas Sep 29 '11 at 10:38

4 Answers4

15

None of the above.

If the object cannot be constructed because of unmet conditions, the constructor should throw an exception with the throw statement.

CharlesB
  • 86,532
  • 28
  • 194
  • 218
  • Unless you call it with `nothrow`. – leftaroundabout Sep 29 '11 at 10:36
  • @leftaroundabout: you can't call a constructor with nothrow() - unless it was defined with throw() (http://stackoverflow.com/questions/1877743/will-using-new-stdnothrow-mask-exceptions-thrown-from-a-constructor) – sehe Sep 29 '11 at 10:38
  • 6
    @leftaroundabout: `nothrow` only means there's no exception when memory can't be allocated. The constructor is still allowed to throw. – sharptooth Sep 29 '11 at 10:38
  • @leftaroundabout nothrow only prevent bad_alloc from being thrown if the program was unable to allocate memory. It doesn't stop your constructor from throwing anything – Alan Sep 29 '11 at 10:38
4

Check before new?

If your preconditions can be verified outside of the object's own inner scope and if they semantically belong in the calling scope, then sure... this is great!

Check within constructor, returning null or something special, don't know how to handle ...

Check within the constructor, and throw an exception. Handle it like you handle any other exception. Best approach.

Check after new was successful and object is alive. Call a member function myObj->Init(). And destroy object if this fails?

Abandoning RAII in this manner is a backwards step.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

Throw an exception for the object's constructor. Note that the object's destructor will not be called, unlike operator delete, which will be called automatically to reclaim the allocated memory.

avakar
  • 32,009
  • 9
  • 68
  • 103
-1

Maybe it's better to make lightweight constructor which always succeeds, and Initialize function that makes heavy work and throws exception on error.

Edit. After some critical feedback, I found why my suggestion doesn't meet RAII requirements: "Resources are acquired during initialization, when there is no chance of them being used before they are available".

I don't change my original post, it may be helpful to have this as typical design error sample.

Alex F
  • 42,307
  • 41
  • 144
  • 212
  • 3
    -1: I've heard this proposed all over the place, because apparently heavy constructors are _bad_. But now [you just lost your RAII](http://stackoverflow.com/questions/810839/throwing-exceptions-from-constructors/810850#810850) and threw away a huge benefit of using C++, causing **all sorts** of error possibilities. Recommending it is _dangerous_, IMO. – Lightness Races in Orbit Sep 29 '11 at 10:40
  • Nothing dangerous, and RAII is not lost. I don't suggest to write Release function that must be called by client. Destructor should release all resources allocated in constuctor, Initialize or anywhere, this is obvious. – Alex F Sep 29 '11 at 10:54
  • 2
    OK, agree, RAII is lost, my fault. – Alex F Sep 29 '11 at 11:00
  • @Tomalak Geret'kal Enlighten me, if the constructors call this init function then how exactly is RAII lost? – DuncanACoulter Sep 29 '11 at 11:03
  • @DuncanACoulter: Why would you have a constructor that calls an init function? That's not what Alex is talking about. – Lightness Races in Orbit Sep 29 '11 at 11:06
  • @Tomalak Geret'kal Why would I do it? Simply to avoid repeating myself if a group of constructors within a class share similar code. "That's not what Alex is talking about." I think I see... by heavy constructor you are referring to resource acquisition that occurs during object creation regardless of whether it was separated into a different (possibly private) member function or not. – DuncanACoulter Sep 29 '11 at 11:15
  • 1
    I'm the _second_ mod to remove comments from this answer. Please, keep comments constructive, friendly and on topic. However, I have cleaned things up so it doesn't look like people were talking to themselves :) – Tim Post Sep 29 '11 at 12:22