Why does `myvector.push_back(autoPtr.release())` provide the strong exception safety guarantee?
EDIT: I should've mentioned, I was looking at the documentation for Boost's ptr_sequence_adapter
and it claims that their adapter for template< class U > void push_back( ::std::auto_ptr<U> x );
is equivalent to doing vec.push_back(autoPtr.release());
and also provides the strong exception guarantee. And then I realized I was confusing their description of the effect of the implementation for what the i开发者_运维百科mplementation actually was, and so this question is semi-nonsensical. I'm just leaving it here for posterity.
To me, it seems the call to std::auto_ptr<t>
would succeed, and then the call to std::vector<t*>::push_back
could throw an exception, and the pointer would be leaked.
It seems like you'd have to do this instead:
vec.push_back(0); //Attempts to allocate space in vector, could throw bad_alloc
vec.back() = autoPtr.release(); //Provides nothrow
This is specifically a feature of the Boost pointer containers library.
The base push_back
member function is defined as:
void push_back( value_type x ) // strong
{
this->enforce_null_policy( x, "Null pointer in 'push_back()'" );
auto_type ptr( x ); // notrow
this->base().push_back( x ); // strong, commit
ptr.release(); // nothrow
}
(from the ptr_sequence_adapter.hpp header)
So, the push_back
function itself takes ownership of the pointer and if reallocation fails, it takes responsibility for deleting the pointer.
The push_back
overload that takes an auto_ptr
is defined in terms of the base push_back
function:
template< class U >
void push_back( std::auto_ptr<U> x )
{
push_back( x.release() );
}
The pointer is released before the call to the base push_back
, which is okay because the base push_back
function has a strong guarantee that it will delete the pointer if an exception is thrown.
Transferring an object out of an auto_ptr releases that auto_ptr's control of the object. It no longer gets the benefits of the auto_ptr. You would have to place the object in another smart pointer in order to become exception safe again, or a container object that gives exception safety guarantees (if there are any?).
Please note that std::auto_ptr cannot be used directly in STL containers. For example, std::vector<auto_ptr<int> > will break. You can have pointers to auto_ptrs, and store the auto_ptrs somewhere else, but auto_ptr copy semantics doesn't jive with STL containers, which rely on copying.
精彩评论