Raider wrote:
Is it exception-safe to write like this:
void foo(auto_ptr<Tx)
{
...
}
void bar()
{
foo(auto_ptr<T>(new T(...));
}
Or should I create temporary variable?
void bar()
{
auto_ptr<Tx(new T(...);
foo(x);
}
In your specific example the usage is exception safe (so far as I can
tell). However, it isn't a bad habit to get into to initialize
auto_ptrs (and shared_ptrs) in a separate variable. Consider what
could happen if you had another parameter.
void foo(auto_ptr<Tx, int y)
{
}
And now you call it using the same style:
int f() { /* whatever */ }
void bar()
{
foo(auto_ptr<T>(new T), f()) ;
}
You've now lost exception safety, depending on how the compiler decides
to order the various operations in the expression. Consider this
ordering:
(1) new T
(2) f()
(3) auto_ptr<T>()
(4) foo()
If (1) succeeds, but (2) throws an exception, then you leak memory.
This could not happen if you used a named auto_ptr instead of a
temporary. If you really hate having your auto_ptrs be automatic
variables, one idiom is to write a version of new that returns an
auto_ptr. Example:
template <typename T>
auto_ptr<Tauto_new()
{
return auto_ptr<T>(new T) ;
}
Then you could call:
foo(auto_new<T>(), f()) ;
The difference between this and the previous attempt is that, while the
compiler may reorder the parts of an operation, it will not reorder
parts of a function (the 'as if' clause notwithstanding), so you are
guarantee that if new succeeds, the result gets put into an auto_ptr
before anything else happens.
The downside of the above approach is that it is not as flexible as
new. Notably, it would only work with constructors that take no
parameters. You could create an overload or separate function for each
type of constructor, but whether that is more or less work than just
making auto_ptr's named variables depends on the details of your
situation.
--
Alan Johnson