Ответ 1
Короткий ответ: это зависит от используемого вами стандарта и реализации библиотеки:
- В С++ 98 и С++ 03 нет движения, поэтому все будет глубоко скопировано, включая перераспределение.
- В С++ 11 и С++ 14 будет глубокая копия, включая перераспределение, или, если реализация предоставляет
noexcept
в конструкторе перемещенияstd::vector<ContactPairs>
. - В предстоящем С++ 17 внутренний вектор будет перемещен и не будет выполнена глубокая копия.
И вот рассуждение:
-
Тип внутренних векторов
std::vector<ContactPairs>
имеет конструктор перемещения, который равенnoexcept
в соответствии с предстоящим стандартом С++ 17 (начиная с N4296) и неnoexcept
в соответствии с стандарты С++ 11 и С++ 14, раздел [vector.modifiers]. Вы также можете найти здесь здесь. Однако даже реализации, совместимые с С++ 11 и С++ 14, могут указыватьnoexcept
, поскольку реализации могут обеспечить более высокие гарантии, чем это предусмотрено стандартом (см. С++ Standard 17.6.5.12). Однако многие реализации не делают этого. -
Реализация
std::vector<T>::push_back()
обязана гарантировать безопасную защиту исключений, т.е. е. если он бросает, побочных эффектов нет. (См. Стандарт С++, раздел [container.requirements.general] §10 или §11 или здесь.) -
Если новый размер вектора, на который вы вызываете
push_back()
, превышает его емкость, тогда память должна быть выделена для нового места, и элементы необходимо скопировать или переместить в новое место. Если перемещение элементов внешнего вектора может завершиться неудачно (нетnoexcept
), то элементы необходимо скопировать, чтобы реализовать сильную гарантию исключения. В этом случае каждая копия внутреннего вектора требует дополнительного распределения. Тем не менее, если перемещениеnoexcept
, то все перемещение в цикле не может быть выбрано и безопасно использовать для реализации надежной гарантии исключения.
Реализация std::vector<T>
перемещение конструкции с гарантией noexcept
кажется тривиальной вещью для std::vector
. Я подозреваю, что комитет по стандартам, возможно, не решался поставить эту гарантию в стандарт для согласованности: для других контейнеров на основе node может быть полезно иметь дозорные узлы, для которых требуется распределение даже для построения по умолчанию. Поскольку перемещенный контейнер должен быть действительным после перемещения, может быть выделение, необходимое для перемещения std::list
, которое может быть выбрано, например. Следовательно, нет гарантии noexcept
для конструктора перемещения std::list
и других стандартных типов контейнеров node.