Как стать автором
Обновить

Комментарии 19

Неплохо, для статьи с названием «краткое введение». Уже использовал rvalue-ссылки в своем коде, но вот про forward например не знал.
Как мне показалось, как раз достаточный минимум материала для практического использования. Меньше — сильно поверхностно и непонятно, больше — много деталей.

Хотя, конечно, кому нужно было, тот уже собрал документацию по интернетам, к примеру вот и вот.

Ещё смущает, что std::move() под одним именем скрывает функцию из для реализации семантики перемещения и функцию из для перемещения элементов из одного диапазона в другой.
Лично мне намного более коротким, понятным и по существу кажется ответ на stackoverflow на вопрос «What is move semantics?». За ним следует более подробный ответ от того же автора.
Ну и в качестве продолжения: perfect forwarding, на мой взгляд, весьма тяжело понять из этой статьи (я не понял, например), а вот по этой ссылке есть действительно полное объяснение (нам особенно важны решения 6 и 7). Более краткое изложение этой ссылки дается в неплохом ответе на stackoverflow, хотя местами тоже скомкано. Мне кажется, можено начать со SO, а если непонятно, обращаться к первой ссылке.
template <class T>
typename remove_reference<T>::type&&
move(T&& a)
{
    return a;
}

Это неправильная реализация std::move. Более того, этот код даже не компилируется, потому что а в данном контексте является lvalue и не может преобразоваться в rvalue. Правильный вариант:

...
move(T&& a)
{
    return static_cast<typename std::remove_reference<T>::type&&>(a);
}
Аналогичная проблема во второй вставке кода:
A a;
A&& a_ref2 = a; // это rvalue ссылка
Нельзя проинициализировать rvalue reference с помощью lvalue expression.
Теперь всё зависит от клиентского кода, где должны быть перегружены ключевые функции (например, конструктор копирования и оператор присваивания), определяющие будет ли параметр lvalue или rvalue. Если параметр lvalue, то необходимо выполнить копирование. Если rvalue, то можно безопасно выполнить перемещение.

Какое-то сложное утверждение. Вроде как правильно, но ни один нормальный человек не поймет, в чем тут соль. После std::move параметр всегда будет rvalue. Но если объект не поддерживает перемещение, то этот параметр может привязаться и к lvalue-ссылке (то бишь, будет вызван конструктор копирования).
Это был ответ Werat'у.
На самом деле, после std::move мы получаем xvalue expression, а уж к чему мы его привяжем (bind) — это следующий вопрос :-)
Верное замечание. Но xvalue — это подмножество rvalue, так что я тоже нигде вроде не ошибся.
Чем дальше ВУЗ, тем меньше я понимаю С++. Это грустно :(
Ох, как верно подмечено! Ваша фраза или откуда-то?
Не, не моё, откуда-то утянул, не помню откуда.
Не опасно ли в следующем коде совершать перемещение базового объекта до перемещения членов унаследованного объекта?

// move semantics
Derived(Derived&& x) // rvalues bind here
: Base(std::move(x)),
vec(std::move(x.vec)),
name(std::move(x.name)) { }

Derived& operator=(Derived&& x) // rvalues bind here
{
Base::operator=(std::move(x));
vec = std::move(x.vec);
name = std::move(x.name);
return *this;
}

Ведь если в базовом классе будет виртуальная функция reset(), которая чистит члены, и которую раширяет унаследованный объект для своих членов, и перемещающие конструктор и оператор присваивания в базовом классе вызывают эту функцию, то члены унаследованного объекта будут очищены до того, как их скопируют.
А функция reset() объявлена как виртуальная или переопределена в Derived?
С точки зрения Base(Base&&) динамический тип объекта так же Base, так что виртуальный вызов reset() будет направлен к Base::reset(), таким образом возможности почистить поля derived типа у reset не будет.
Небольшая поправка по поводу «rvalues bind here», привязываются ссылки, а не выражения. То есть корректный комментарий будет «rvalue reference binds to rvalue expressions».
Точно :) Но для оператора присваивания проблема остаётся.
Поэтому для иерархий типов с виртуальными членами обычно запрещают вызов копирующего конструктора и оператора присваивания, заменяя их на Clone.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории