Re: How to make this exception-safe
On 19 Nov, 22:30, Richard Smith <rich...@ex-parrot.com> wrote:
On Nov 18, 6:43 pm, Triple-DES <DenPlettf...@gmail.com> wrote:
How would you go about making an exception-safe version of V::V()?
This is what I could come up with: [...]
V::V() {
v_.reserve(3);
std::auto_ptr<C> c1( new C(2) );
std::auto_ptr<C> c2( new C(1) );
std::auto_ptr<C> c3( new C(3) );
v_.push_back( c1.release() );
v_.push_back( c2.release() );
v_.push_back( c3.release() );
}
Why bother with the auto_ptrs? Once you have done the reserve, the
call to push_back is not permitted to cause a reallocation (assuming
you passed the right argument to reserve). The only other thing that
push_back does that might, in general, throw an exception is call the
copy constructor of the vector's value_type. However, in your code,
the value_type is C* -- a raw pointer -- and its copy constructor will
never throw.
But C::C may throw. Thus the need for the auto_ptr.
So you can simply write:
v_.reserve(3);
v_.push_back( new C(1) );
v_.push_back( new C(2) );
v_.push_back( new C(3) );
See above. A solution like this needs to be wrapped inside a try
block.
If the list of elements to be inserted is significantly longer than 3,
or if it's likely to be changed over time, I might do something like:
size_t const expected_size = 3;
v_.reserve(expected_size);
// ... call v_.push_back 3 times
assert( v_.size() == expected_size );
That way, if someone adds another push_back to the function, but
forgets to alter the reserve call, you will get an assertion failure
that will (hopefully!) be picked up during testing.
It would be picked up during a scrutinous peer review (wishful
thinking).
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]