Я пытаюсь понять семантику перемещения и скопировать/переместить elision.
Мне нужен класс, который обертывает некоторые данные. Я хотел бы передать данные в конструкторе, и я хотел бы иметь данные.
После чтения this, this и this У меня сложилось впечатление, что в С++ 11, если я хочу сохранить копию, тогда пропускная способность должна быть не менее эффективной, чем любая другая опция (кроме незначительная проблема увеличения размера кода).
Затем, если вызывающий код хочет избежать копирования, он может, передав rvalue вместо lvalue. (например, используя std:: move)
Итак, я попробовал:
#include <iostream>
struct Data {
Data() { std::cout << " constructor\n";}
Data(const Data& data) { std::cout << " copy constructor\n";}
Data(Data&& data) { std::cout << " move constructor\n";}
};
struct DataWrapperWithMove {
Data data_;
DataWrapperWithMove(Data&& data) : data_(std::move(data)) { }
};
struct DataWrapperByValue {
Data data_;
DataWrapperByValue(Data data) : data_(std::move(data)) { }
};
Data
function_returning_data() {
Data d;
return d;
}
int main() {
std::cout << "1. DataWrapperWithMove:\n";
Data d1;
DataWrapperWithMove a1(std::move(d1));
std::cout << "2. DataWrapperByValue:\n";
Data d2;
DataWrapperByValue a2(std::move(d2));
std::cout << "3. RVO:\n";
DataWrapperByValue a3(function_returning_data());
}
Вывод:
1. DataWrapperWithMove:
constructor
move constructor
2. DataWrapperByValue:
constructor
move constructor
move constructor
3. RVO:
constructor
move constructor
Мне было приятно, что ни в одном из этих случаев не вызван конструктор копирования, но почему в втором случае есть дополнительный конструктор перемещения? Я предполагаю, что любой достойный конструктор перемещения для Data
должен быть довольно быстрым, но он все еще меня пьет. У меня возникает соблазн использовать ссылку pass-by-rvalue-reference (первый вариант), так как это, по-видимому, приводит к одному вызову конструктора с меньшим числом движений, но я хотел бы использовать pass-by-value и copy elision, если можно.