используя 2 метода для извлечения данных в контейнере (pop_front и front)

( Извините за мой плохой английский! )
Привет, я учусь на промышленных компьютерах. Это мой пятый срок. В одном из моих курсов учитель попросил нас написать класс «Список» (только вперед, 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?

Спасибо за помощь!

1

Решение

Я не понимаю, почему мы не можем сделать это одним способом?

Эти две операции необходимы, чтобы дать надежную гарантию исключения — то есть, если исключение выдается в любое время, контейнер не должен быть изменен.

Ваше предложение, auto v = something.pop(), должен сделать три вещи по порядку:

  • Удалить элемент из контейнера;
  • Вернуть этот элемент из функции;
  • Инициализировать v с возвращенным значением.

Если на последнем этапе возникает исключение, то элемент будет удален из контейнера и потерян. Ваша попытка исправить это с try...catch Конструкция не поможет: исключение будет сгенерировано после возврата из функции и поэтому не будет перехвачено обработчиком в функции.

Делая это в два этапа с интерфейсом в стиле STL, вместо этого порядок:

  • Обработать ссылку на элемент контейнера;
  • Удалить элемент из контейнера.

Теперь, если обработка выдает исключение, элемент остается в контейнере и не теряется.

В наши дни, с добавлением семантики перемещения в язык, вы мог реализовать вашу версию с требованием, чтобы элементы не выбрасывались при перемещении. Это довольно разумное требование, уже сделанное некоторыми операциями над контейнерами C ++ 11. Но этого не произошло, и я сомневаюсь, что такое изменение будет сделано только для незначительного удобства.

Если мы действительно заботимся об исключении, которое может быть добавлено в конструктор копирования, и мы действительно хотим продолжить И сохранить данные, разве мы не можем просто попытаться обойти метод pop?

Мы могли бы; но это менее удобно и намного более подвержено ошибкам, чем обеспечение безопасного интерфейса.

0

Другие решения

STL выполняет две операции, потому что функция front () возвращает ссылку, а не значение, чтобы исключить двойные копии. Удаление элемента из списка при возврате элемента потребует возврата по значению, в противном случае объект уже выйдет из области видимости.

0

По вопросам рекламы [email protected]