Почему pop_back()
не имеет возвращаемого значения? У меня есть Googled относительно этого и выяснил, что он делает его более эффективным. Это единственная причина, по которой это делается в стандарте?
Pop_back() возвращаемое значение?
Ответ 1
Я думаю, что есть что-то, связанное с тем, что копирование экземпляра последнего объекта может вызвать исключение. При этом вы теряете свой объект, так как pop_back() удалил его из вашего контейнера. Лучше с несколькими строками кода:
std::vector<AnyClass> holds = {...} ;
try {
const AnyClass result = holds.pop_back(); // The copy Ctor throw here!
} catch (...)
{
// Last value lost here.
}
Ответ 2
Эффективность мало (или ничего, действительно) для этого.
Этот проект является результатом важной статьи Тома Каргилла, опубликованной в 90-х годах, которая тогда подняла немало бровей. IIRC, в ней Cargill показал, что невозможно создать безопасную функцию pop pop исключений.
Ответ 3
Это из-за принципа разделения командного запроса.
Ответ 4
Эффективность - это одно. Другой причиной для pop_back()
не возврата элемента является безопасность исключений.
Если функция pop()
вернула значение и исключение генерирует конструктор копирования, вы не сможете гарантировать, что контейнер находится в том же состоянии, что и до вызова pop()
.
Вы можете найти больше информации в книгах Herb Sutters об исключениях. Я думаю, что эта тема освещена здесь. Но я не уверен.
Ответ 5
Причина заключается не столько в эффективности, сколько в безопасности исключений. Класс контейнера может использоваться для хранения любых объектов. Было бы невозможно реализовать pop_back() безопасным образом, если функция вернет объект после удаления его из контейнера, потому что возврат значения объекта включает создание копии.
Это фактическая реализация vector:: pop_back() в стандартной библиотеке GNU С++:
void
pop_back()
{
--this->_M_impl._M_finish;
this->_M_impl.destroy(this->_M_impl._M_finish);
}
Это будет выглядеть, если он вернет последний элемент в конце:
value_type
pop_back()
{
value_type save = back();
--this->_M_impl._M_finish;
this->_M_impl.destroy(this->_M_impl._M_finish);
return save;
}
Это включает в себя две копии конструкций в операторе save = back()
и при возврате копии объекта. Нет никаких гарантий того, что выражение return не будет генерировать исключение после уничтожения элемента из контейнера.
Ответ 6
Ну, сколько причин должно быть?
Это позволяет избежать потенциально дорогого копирования объекта, когда вы просто хотите удалить его из контейнера. С++ имеет философию не платить за то, что вам не нужно.
Ответ 7
Почему бы это вернуть значение? Вы всегда можете получить доступ к значению в любое время до его выключения - нет необходимости в pop_back
для обеспечения этой функции.