Pop_back() возвращаемое значение?

Почему pop_back() не имеет возвращаемого значения? У меня есть Googled относительно этого и выяснил, что он делает его более эффективным. Это единственная причина, по которой это делается в стандарте?

Ответ 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 исключений.

Ответ 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 для обеспечения этой функции.