Подтвердить что ты не робот

Почему С++ перемещает семантику, оставляя построенный источник?

В С++ 11 была введена "семантика перемещения", реализованная через два специальных элемента: move constructor и move assign. Обе эти операции оставляют сконструированный перемещенный объект.

Не было бы лучше оставить источник в разрушенном состоянии? Разве не единственное, что вы можете сделать с перемещенным объектом, все равно разрушает его?

4b9b3361

Ответ 1

В "вселенной операций перемещения" есть четыре возможности:

target          source
  is            is left
----------------------------------------------------------
constructed <-- constructed  // C++11 -- move construction
constructed <-- destructed
assigned    <-- constructed  // C++11 -- move assignment
assigned    <-- destructed

Каждая из этих операций полезна! Только std::vector<T>::insert может использовать первые три. Хотя обратите внимание:

  • У источника 2-го и 4-го не должно быть автоматического, статического или потокового хранилища. Длительность хранения источника должна быть динамической, иначе компилятор вызовет деструктор на уже разрушенном объекте. И нет, компилятор не может (в общем) отслеживать, если объект был перемещен - из:

X x1, x2;
if (sometimes)
{
    x1 = std::move(x2);
}
// Is x2 moved-from here?

  • 2-й и 4-й могут быть эмулированы 1-й и 3-й соответственно, просто вручную вызывая деструктор на источнике после операции.

  • Первый и третий имеют решающее значение. Алгоритмы, такие как std::swap и std::sort, регулярно нуждаются в обеих этих операциях. Этим алгоритмам не нужно уничтожать ни один из своих входных объектов — изменять их значения.

Вооружившись этими знаниями, в период 2001-2002 годов я сосредоточил свои усилия на двух операциях, которые оставили их источник, потому что эти две операции будут иметь наибольшее (положительное) влияние на то, что было тогда С++ 98. В то время я знал, что, если я не ограничу амбиций этого проекта, это никогда не будет успешным. Даже свернувшись, это было слишком грандиозным, чтобы преуспеть.

Это сокращение признано в исходном предложении семантики переноса в разделе "Разрушающая семантика перемещения".

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

Подробнее о том, что можно сделать с перемещенным объектом, см. fooobar.com/info/55000/...