Re: How to make this exception-safe
On 18 Nov., 19:43, Triple-DES <DenPlettf...@gmail.com> wrote:
Consider the following code:
#include <vector>
struct C {
explicit C(int) {} // may throw
private:
C(const C&);
C& operator=(const C&);
};
struct V {
V() {
// may leak if push_back or C::C(int) throws
v_.push_back( new C(2) );
v_.push_back( new C(1) );
v_.push_back( new C(3) );
}
~V() {} // delete all elems of v
private:
std::vector<C*> v_;
};
How would you go about making an exception-safe version of V::V()?
This is what I could come up with:
// 1st attempt
#include <memory>
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() );
}
Note that this approach would still have
an observable change of v_, if one of the
created C items throws, because the initial
change of the container capacity is not undone.
I just want to notice that, because you did
not specify the degree of exception-safe.
If this is ok, you seem to accept the so-called
basic guarantee.
Which is tedious if you are inserting more objects. Does anyone have a
better solution?
Two approaches come into my mind, both would
use a helper function to do the dirty work
(Generalize the following as templates, if you
like):
1) Combine reserve and C-allocation - no RAII necessary:
void add(std::vector<C*>& v, int arg) {
v.reserve(v.size() + 1); // Might throw
v.push_back(new C(arg)); // If construction of C fails,
// the container size is still the original one.
// push_back cannot fail here, see [vector.capacity]/6
}
2) Combine RAII and
void add(std::vector<C*>& v, int arg) {
std::auto_ptr<C> buf(new C(arg)); // Might throw
v.push_back(buf.get()); // push_back might fail, but buf is
// our rescue
buf.release(); // Cannot fail
}
In either case your code becomes easy:
struct V {
V() {
add(v_, 2);
add(v_, 1);
add(v_, 3);
}
...
};
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]