( Извините за мой плохой английский! )
Привет, я учусь на промышленных компьютерах. Это мой пятый срок. В одном из моих курсов учитель попросил нас написать класс «Список» (только вперед, ptr к следующему элементу, но не к предыдущему) в c. Я сделал простой метод извлечения, который возвращает value_type и удаляет первый элемент, но мой учитель сказал, что если конструктор копирования выдает исключение, значение будет потеряно, поскольку оно было извлечено. Я посмотрел на std :: forward_list и увидел, что stl предлагает метод для извлечения и метод для доступа к последнему элементу (pop_front () и front ()).
Я не понимаю, почему мы не можем сделать это одним способом?
Я написал этот код:
value_type extract()
{
if( empty() )
throw EmptyList();
std::unique_ptr< Node > p = m_Head;
if( m_Head == m_Last )
m_Last = nullptr;
m_Head = m_Head->m_Next;
try
{
return p->m_Value;
}
catch( ... )
{
m_Head = p.release();
if( !m_Last )
m_Last = m_Head;
throw;
}
}
Я также сделал метод extract с параметром nothrow_t, который ничего не копирует (return void), чтобы мы могли «форсировать» извлечение.
Почему STL не делает этого? Было бы неплохо сделать «auto v =thing.pop ();» !
Моя версия безопасна? Если мы действительно заботимся об исключении, которое может быть добавлено в конструктор копирования, и мы действительно хотим продолжить И сохранить данные, разве мы не можем просто попытаться обойти метод pop?
Спасибо за помощь!
Я не понимаю, почему мы не можем сделать это одним способом?
Эти две операции необходимы, чтобы дать надежную гарантию исключения — то есть, если исключение выдается в любое время, контейнер не должен быть изменен.
Ваше предложение, auto v = something.pop()
, должен сделать три вещи по порядку:
v
с возвращенным значением.Если на последнем этапе возникает исключение, то элемент будет удален из контейнера и потерян. Ваша попытка исправить это с try...catch
Конструкция не поможет: исключение будет сгенерировано после возврата из функции и поэтому не будет перехвачено обработчиком в функции.
Делая это в два этапа с интерфейсом в стиле STL, вместо этого порядок:
Теперь, если обработка выдает исключение, элемент остается в контейнере и не теряется.
В наши дни, с добавлением семантики перемещения в язык, вы мог реализовать вашу версию с требованием, чтобы элементы не выбрасывались при перемещении. Это довольно разумное требование, уже сделанное некоторыми операциями над контейнерами C ++ 11. Но этого не произошло, и я сомневаюсь, что такое изменение будет сделано только для незначительного удобства.
Если мы действительно заботимся об исключении, которое может быть добавлено в конструктор копирования, и мы действительно хотим продолжить И сохранить данные, разве мы не можем просто попытаться обойти метод pop?
Мы могли бы; но это менее удобно и намного более подвержено ошибкам, чем обеспечение безопасного интерфейса.
STL выполняет две операции, потому что функция front () возвращает ссылку, а не значение, чтобы исключить двойные копии. Удаление элемента из списка при возврате элемента потребует возврата по значению, в противном случае объект уже выйдет из области видимости.