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

РЕДАКТИРОВАТЬ: я должен был упомянуть, я искал документацию для Boost'sptr_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 ответа

Решение

Это особенность библиотеки контейнеров указателей 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 Функция имеет строгую гарантию, что она удалит указатель, если возникнет исключение.

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

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

Другие вопросы по тегам