Comments 19
Неплохо, для статьи с названием «краткое введение». Уже использовал rvalue-ссылки в своем коде, но вот про forward например не знал.
+2
Как мне показалось, как раз достаточный минимум материала для практического использования. Меньше — сильно поверхностно и непонятно, больше — много деталей.
Хотя, конечно, кому нужно было, тот уже собрал документацию по интернетам, к примеру вот и вот.
Ещё смущает, что std::move() под одним именем скрывает функцию из для реализации семантики перемещения и функцию из для перемещения элементов из одного диапазона в другой.
Хотя, конечно, кому нужно было, тот уже собрал документацию по интернетам, к примеру вот и вот.
Ещё смущает, что std::move() под одним именем скрывает функцию из для реализации семантики перемещения и функцию из для перемещения элементов из одного диапазона в другой.
+1
Ну и в качестве продолжения: perfect forwarding, на мой взгляд, весьма тяжело понять из этой статьи (я не понял, например), а вот по этой ссылке есть действительно полное объяснение (нам особенно важны решения 6 и 7). Более краткое изложение этой ссылки дается в неплохом ответе на stackoverflow, хотя местами тоже скомкано. Мне кажется, можено начать со SO, а если непонятно, обращаться к первой ссылке.
+3
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);
}
+1
Теперь всё зависит от клиентского кода, где должны быть перегружены ключевые функции (например, конструктор копирования и оператор присваивания), определяющие будет ли параметр lvalue или rvalue. Если параметр lvalue, то необходимо выполнить копирование. Если rvalue, то можно безопасно выполнить перемещение.
Какое-то сложное утверждение. Вроде как правильно, но ни один нормальный человек не поймет, в чем тут соль. После std::move параметр всегда будет rvalue. Но если объект не поддерживает перемещение, то этот параметр может привязаться и к lvalue-ссылке (то бишь, будет вызван конструктор копирования).
0
Это был ответ Werat'у.
На самом деле, после std::move мы получаем xvalue expression, а уж к чему мы его привяжем (bind) — это следующий вопрос :-)
На самом деле, после std::move мы получаем xvalue expression, а уж к чему мы его привяжем (bind) — это следующий вопрос :-)
+1
Чем дальше ВУЗ, тем меньше я понимаю С++. Это грустно :(
0
Не опасно ли в следующем коде совершать перемещение базового объекта до перемещения членов унаследованного объекта?
// 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(), которая чистит члены, и которую раширяет унаследованный объект для своих членов, и перемещающие конструктор и оператор присваивания в базовом классе вызывают эту функцию, то члены унаследованного объекта будут очищены до того, как их скопируют.
// 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(), которая чистит члены, и которую раширяет унаследованный объект для своих членов, и перемещающие конструктор и оператор присваивания в базовом классе вызывают эту функцию, то члены унаследованного объекта будут очищены до того, как их скопируют.
+1
А функция reset() объявлена как виртуальная или переопределена в Derived?
0
С точки зрения Base(Base&&) динамический тип объекта так же Base, так что виртуальный вызов reset() будет направлен к Base::reset(), таким образом возможности почистить поля derived типа у reset не будет.
Небольшая поправка по поводу «rvalues bind here», привязываются ссылки, а не выражения. То есть корректный комментарий будет «rvalue reference binds to rvalue expressions».
Небольшая поправка по поводу «rvalues bind here», привязываются ссылки, а не выражения. То есть корректный комментарий будет «rvalue reference binds to rvalue expressions».
0
Sign up to leave a comment.
Краткое введение в rvalue-ссылки