Возможный дубликат:
Как применять семантику перемещения при росте вектора?
insert
, push_back
и emplace
(_back
) могут привести к перераспределению a std::vector
. Я был озадачен, увидев, что следующий код копирует элементы, а не перемещает их при перераспределении контейнера.
#include <iostream>
#include <vector>
struct foo {
int value;
explicit foo(int value) : value(value) {
std::cout << "foo(" << value << ")\n";
}
foo(foo const& other) noexcept : value(other.value) {
std::cout << "foo(foo(" << value << "))\n";
}
foo(foo&& other) noexcept : value(std::move(other.value)) {
other.value = -1;
std::cout << "foo(move(foo(" << value << "))\n";
}
~foo() {
if (value != -1)
std::cout << "~foo(" << value << ")\n";
}
};
int main() {
std::vector<foo> foos;
foos.emplace_back(1);
foos.emplace_back(2);
}
На моей конкретной машине, использующей мой конкретный компилятор (GCC 4.7), это печатает следующее:
foo(1)
foo(2)
foo(foo(1))
~foo(1)
~foo(1)
~foo(2)
Однако при удалении конструктора копирования (foo(foo const&) = delete;
) генерируется следующий (ожидаемый) вывод:
foo(1)
foo(2)
foo(move(foo(1))
~foo(1)
~foo(2)
Почему? Скорее всего, будет более эффективным или, по крайней мере, не менее эффективным, чем копирование?
Следует отметить, что GCC 4.5.1 делает ожидаемую вещь - это регрессия в GCC 4.7 или это какая-то хитроумная оптимизация потому что компилятор видит, что мой объект дешево копировать (но как?!)?
Также обратите внимание, что я убедился, что это вызвано перераспределением, экспериментально помещая foos.reserve(2);
перед вставками; это не вызывает ни копирования, ни перемещения для выполнения.