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

Будет ли std::vectors внутри другого вектора перераспределяться при перераспределении первого вектора?

У меня есть вектор std::vector<std::vector<ContactPairs>> m_contactPairs;

Если я назову m_contactPairs.push_back() или любую другую функцию, которая изменит размер самого внешнего вектора, будут ли элементы внутри этого вектора перераспределены (внутренние элементы в этом случае будут std::vector<ContactPairs>), или внутренние векторы просто сделают неглубокой копии и продолжайте указывать на ту же самую память, которую они уже имеют?

Я использую Visual Studio 2010, который предшествует С++ 11, но имеет некоторые функции в качестве расширений

4b9b3361

Ответ 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.

Ответ 2

В С++ 03 перераспределение std::vector будет скопировать ( "глубокая копия" ) каждого элемента. Это означает, что для вашей ситуации каждый вектор будет скопирован.

В С++ 11 или более поздней версии перераспределение std::vector будет перемещать каждый элемент , только если, у элементов есть конструктор перемещения, который noexcept.

В Visual Studio 2010 отсутствует поддержка noexcept, поэтому вы все равно получите глубокую копию.