Is the following definition bad style or plain wrong? That is, is it wrong to throw after having intialized a value that is considered incorrect?
myClass::myClass(int arg) : value(arg)
{
if (value < 0)
throw (myException("Negative value not allowed!"));
}
It seems preferable to use the intializer-list over assigning the value in the body, and from what I understand it does not matter if I throw after the value has been assigned or before.
If
valuebeing >= 0 is a class invariant, then you really only have a couple of possibilities. One would be to write the ctor to accept aunsignedparameter, so a value <0 simply wasn’t possible. The other is to throw an exception.But yes, if the user passes a value from which you can’t create a valid object, then throwing an exception is entirely acceptable (and generally the right thing to do). The constructor’s responsibility is to create a valid object. If it’s passed a value from which it cannot create a valid object, than an exception is generally the correct response.
As to when to throw the exception: at least in this case, it doesn’t really matter. The exception will roll-back creation of the current object, so it will never exist anyway. It could make a difference if it was a lot faster to test the value first, rather than copying the value then destroying it if it was invalid. With things like
intthat’s pretty much irrelevant. If you had, say, a large tree of some sort, and could tell whether it was valid by looking only at, say, the root node of the tree, it would probably be better to inspect that node first, and only copy the three if it was valid.The latter is obviously an optimization, but can be a big enough and simple enough one that it may be worthwhile even without profiling (arguably, it’s less optimization that just avoiding pessimization).