Семантика перемещения с членом std::vector

Извините, если об этом уже спрашивали, но, насколько я понимаю, в С++ 11 std::vector имеет конструктор перемещения, так что копии почти ничего не стоят в определенных ситуациях, например, возвращая единицу по значению. Однако, если у меня есть такой класс с vector в качестве переменной-члена:

class MyClass {
public:
    MyClass() { }
    MyClass(const MyClass& rhs) { }

    // other interfaces

private:
    std::vector<int> myvec;

    // implementation
};

И есть функция, которая возвращает один из них по значению, например

MyClass somefunc() {
    MyClass mc;
    // fill mc.myvec with thousands (maybe even millions) of ints
    return mc;
}

Будет ли вызываться конструктор перемещения mc.myvec и использоваться конструктор перемещения std::vector, даже если сам MyClass ничего не знает о конструкторах перемещения? Или будет вызван конструктор копирования vector и все эти тысячи (может быть, даже миллионы) int должны быть скопированы один за другим?


person Seth Carnegie    schedule 24.11.2011    source источник
comment
Более того, копия будет исключена любым современным компилятором, реализующим NRVO.   -  person K-ballo    schedule 24.11.2011
comment
@K-ballo: Зависит от того, что пишет звонящий. Если это MyClass mc; /* other code */ if (something) { mc = somefunc(); } else { mc = someotherfunc(); } или иным образом используется возвращаемое значение функции в качестве правой стороны присваивания, то NRVO не препятствует копированию присваивания. Если вы собираетесь писать функции, основанные на NRVO для базовой эффективности, вам нужно убедиться, что класс либо эффективно перемещается, либо может быть эффективно заменен, чтобы выявить случаи, когда NRVO неприменим.   -  person Steve Jessop    schedule 24.11.2011


Ответы (1)


Если вы не пишете никаких явных конструкторов копирования или перемещения или каких-либо операторов присваивания копирования или перемещения или деструктора, то предоставленный по умолчанию конструктор перемещения перемещает элементы один за другим. Подробнее см. 12.8.9.

Поскольку вы определяете свой собственный конструктор копирования, вы не получите конструктор перемещения по умолчанию. Либо определите один (возможно, = default), либо избавьтесь от явного конструктора копирования.

Хорошо составленные классы обычно не нуждаются в какой-либо пользовательской Большой пятерке, а вместо этого полагаются на участников, предоставляющих их, и используют версию по умолчанию.

person Kerrek SB    schedule 24.11.2011
comment
Итак, предоставленный по умолчанию конструктор перемещения вызывает конструкторы перемещения всех переменных-членов? - person Seth Carnegie; 24.11.2011
comment
@SethCarnegie: Да, действительно. Вы можете попробовать это, создав класс, содержащий unique_ptr, и инициализировать его из функции, которая возвращает класс по значению, и это должно работать. - person Kerrek SB; 24.11.2011
comment
Блин, большое спасибо за быстрый ответ и разъяснение. Я приму этот ответ, когда срок истечет. - person Seth Carnegie; 24.11.2011