Ответ 1
К сожалению, это не гарантируется. Тем не менее, это означает, что все 3 текущих реализации (libС++, libstdС++ и VS-2015) гарантируют это. Вопрос в том, не является ли конструктором перемещения для A
:
static_assert(std::is_nothrow_move_constructible<A>::value, "");
Конструктор перемещения для A
является компилятором и, следовательно, зависит от конструктора перемещения std::vector<int>
. Если конструктор перемещения std::vector<int>
не является исключением, то конструктор перемещения для A
не является исключением, иначе это не так.
Текущий проект N4296 не помещает конструктор перемещения для vector
как noexcept. Однако это позволяет реализациям делать это.
Эта строка:
aVec.resize(30);
Будет использовать конструктор move A
, если этот конструктор перемещения не существует, иначе он будет использовать конструктор A
copy. Если он использует конструктор A
copy, местоположение ints изменится. Если он использует конструктор перемещения A
, расположение int будет оставаться стабильным.
libС++ и libstdС++ mark vector
переместить конструктор как noexcept. И, таким образом, дайте A
конструктор move noexcept.
VS-2015 говорит, что A
не имеет конструктора move noexcept:
static_assert(std::is_nothrow_move_constructible<A>::value, "");
не компилируется.
Тем не менее, VS-2015 не перераспределяет int на новый адрес, и, похоже, он не соответствует спецификации С++ 11.
Если кто-то изменяет заголовки libС++, так что конструктор перемещения vector
не помечен noexcept, тогда ints действительно перераспределяются.
Недавние обсуждения в комитете показывают, что все выступают за маркировку конструктора перемещения vector
noexcept (и, возможно, basic_string
тоже, но не других контейнеров). Таким образом, возможно, что будущий стандарт гарантирует стабильность, которую вы ищете. Тем временем, если:
static_assert(std::is_nothrow_move_constructible<A>::value, "");
компилируется, тогда у вас есть гарантия, иначе вы этого не сделаете.
Обновление
Причина, по которой x2 != y2
в обновлении заключается в том, что это адреса vector<int>
в vector<vector<int>>
. Этим внутренним элементам пришлось найти новый (больший) буфер, в котором можно было бы жить, точно так же, как если бы внутренний элемент был int
. Но в отличие от int
, внутренний элемент vector<int>
мог перемещаться туда с помощью конструктора перемещения (int
пришлось копировать). Но нужно ли перемещать или копировать адрес внутреннего элемента (от небольшого старого буфера до большого нового буфера). Это поведение согласуется с исходной частью вопроса (где также отображается внутренний элемент для изменения адресов).
И да, LWG 2321 участвует, хотя и не спорный момент. В моем ответе я уже предполагал LWG 2321. Нет никакого другого способа избежать событий, кроме чрезмерно нетерпеливых отладочных итераторов, чтобы безвозмездно (и неправильно) аннулировать себя. Итераторы без отладки никогда не будут аннулированы, и не будут указатели или ссылки.
Желаю, чтобы у меня была возможность легко создавать анимацию со стрелками в буферы. Это было бы действительно ясно. Я просто не знаю, как легко сделать это за время, которое у меня есть.