tl; dr : std::vector
будет копировать вместо перемещения, если ваш конструктор перемещения не noexcept
.
1. Речь идет не о членах, а о динамических c распределениях
Проблема не в том, что вы делаете с полями foo. Таким образом, ваш источник может быть просто:
class foo {
public:
foo(size_t num) {}
~foo() = default
foo(foo const& other) {
std::cout << "copy..." <<std::endl;
}
foo(foo&& other) {
std::cout << "move..." << std::endl;
}
foo& operator=(foo const& other) {
std::cout << "copy assignment..." << std::endl;
return *this;
}
foo& operator=(foo&& other) {
std::cout << "move assignment..." << std::endl;
return *this;
}
};
, и вы все равно получаете такое же поведение: попробуйте .
2. Ход, который вы видите, отвлекает
Теперь push_back()
сначала создаст элемент - в данном случае foo
; затем убедитесь, что в векторе есть место для него; тогда std::move()
это на свое место. Итак, 3 из ваших ходов такого рода. Давайте попробуем использовать emplace_back()
вместо этого, что создаст элемент вектора на его месте:
#include <vector>
#include <iostream>
struct foo { // same as above */ };
int main() {
std::vector<foo> v;
v.emplace_back(10);
v.emplace_back(20);
v.emplace_back(30);
return 0;
}
Это даст нам:
copy
copy
copy
попробуем . Так что ходы были просто отвлечением.
3. Копии происходят из-за изменения размера вектора
Ваш std::vector
постепенно увеличивается при вставке элементов, что требует либо перемещения, либо копирования конструкций. Подробнее см. @ сообщение NutCracker .
4. Реальная проблема - исключения
Смотрите этот вопрос:
Как применить семантику перемещения при росте вектора?
std::vector
не знает он может безопасно перемещать элементы при изменении размера - где «безопасно» означает «без исключений», поэтому он возвращается к копированию.
5. «Но мой копирующий ctor тоже может выдавать исключение!»
Я думаю, логическое обоснование состоит в том, что если вы получаете исключение при копировании меньшего буфера - вы все равно не коснулись его, так что, по крайней мере, ваш оригинальный, не -размерный вектор действителен и может быть использован. Если вы начали перемещение элементов и получили исключение - тогда у вас все равно нет действительной копии элемента, не говоря уже о действительном меньшем векторе.