Почему `myvector.push_back (autoPtr.release ())` обеспечивает строгую гарантию безопасности исключений? - PullRequest
1 голос
/ 08 августа 2010

РЕДАКТИРОВАТЬ: Я должен был упомянуть, я искал документацию для Boost's ptr_sequence_adapter, и он утверждает, что их адаптер для template< class U > void push_back( ::std::auto_ptr<U> x ); эквивалентен делать vec.push_back(autoPtr.release()); а также предоставляет гарантию сильных исключений.А потом я понял, что путаю их описание влияния реализации на то, чем на самом деле была реализация, и поэтому этот вопрос полусмысленный.Я просто оставляю это здесь для потомков.

Мне кажется, вызов std::auto_ptr<t> будет успешным, и тогда вызов std::vector<t*>::push_back может вызвать исключение, и указатель будет просочиться.

Похоже, вы должны сделать это вместо этого:

vec.push_back(0); //Attempts to allocate space in vector, could throw bad_alloc
vec.back() = autoPtr.release(); //Provides nothrow

Ответы [ 2 ]

1 голос
/ 08 августа 2010

Это особенность библиотеки контейнеров указателей Boost.

Базовая push_back функция-член определяется как:

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
}

(из заголовка ptr_sequence_adapter.hpp )

Таким образом, сама функция push_back получает владение указателем, а в случае сбоя перераспределения берет на себя ответственность за удаление указателя.

Перегрузка push_back, которая принимает auto_ptr, определяется в терминах базовой push_back функции:

template< class U >
void push_back( std::auto_ptr<U> x )
{
    push_back( x.release() );
}

Указатель освобождается перед вызовом к базовому push_back, что нормально, потому что базовая функция push_back имеет строгую гарантию, что она удалит указатель в случае возникновения исключения.

0 голосов
/ 08 августа 2010

Перенос объекта из auto_ptr освобождает его от auto_ptr. Это больше не получает преимущества auto_ptr. Вам придется поместить объект в другой интеллектуальный указатель, чтобы снова стать безопасным для исключений, или в контейнерный объект, который дает гарантии безопасности для исключений (если они есть?).

Обратите внимание, что std :: auto_ptr нельзя использовать напрямую в контейнерах STL. Например, std :: vector > сломается. Вы можете иметь указатели на auto_ptrs и хранить auto_ptrs где-то еще, но семантика копирования auto_ptr не совпадает с контейнерами STL, которые полагаются на копирование.

...