On Thu, Apr 21, 2016 at 3:05 PM, Eric Rescorla <e...@rtfm.com> wrote: > The general problem that > it doesn't alleviate is that failure to check the return value leaves you > with a reference/pointer to an object in an ill-defined half-constructed > state. At least for heap allocations, I'd much rather have the property that > failures leave you with a null pointer.
First of all, with neither approach do you end up with a null pointer, at least not in Gecko where we have infallible new. So let's ignore that sentence. As for the notion of a half-constructed object.... With constructor+Init you have three possible object states in a well-coded class. - Half-constructed (i.e. after the constructor runs, but before Init() is called). The destructor shouldn't need to handle this. - Fully-constructed (after successful Init()). The destructor needs to handle this. - Fully-failed (after failed Init()). The destructor needs to handle this. With constructor+outparam you have two possible object states in a well-coded class. - Fully-constructed (after successful construction). The destructor needs to handle this. - Fully-failed (after failed construction). The destructor needs to handle this. You can still screw up in three ways with either approach. - If, on failure, you don't appropriately roll back any partial initialization already done, bad things could happen. E.g. you could leak resources that you've allocated, or you could leave things in a state that causes problems for the destructor. - If your destructor doesn't handle both the fully-constructed case (unlikely) and the fully-failed case (see the crash in bug 1265035). - If you forget to check for failure at your call sites. None of this affects my proposal. All the mistakes you can make with constructor+outparam have the same or extremely similar mistakes possible with constructor+Init. But with my proposal you can use references and |const| in more places, and the code ends up looking nicer because you do everything in one function instead of two. > So, if we are going to do something along these lines, I would want it to be > a convention that if you use MakeUnique and the like (as you should) then > they automatically validate correct construction and if not return an empty > pointer. MakeUnique() just allocates and calls the constructor. If you have fallible steps in your intialization then MakeUnique() won't help you; you'll still have either call your Init() function afterwards or check your nsresult& outparam. So that's not relevant. Maybe you're referring to factory methods, like this: static T* T::New(); which would return null on failure. Such methods can be useful, but there's two problems. First, they're not applicable to stack-allocated objects. Second, you still have to do your fallible initialization *within* the factory method, and so you still have to choose with either constructor+Init or constructor+outparam, so you still have to make a choice. Nick _______________________________________________ dev-platform mailing list dev-platform@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-platform