Имеют ли встроенные типы семантику перемещения?

Рассмотрим этот код:

#include <iostream>
using namespace std;

void Func(int&& i) {
    ++i;
}

int main() {
    int num = 1234;
    cout << "Before: " << num << endl;
    Func(std::move(num));
    cout << "After: " << num << endl;
}

Его вывод:

Before: 1234
After: 1235

Ясно, что i изменяется внутри Func, так как он привязан к параметру i после того, как был "преобразован" в ссылку r-значения с помощью std::move.

Ну, моя точка зрения:

Перемещение объекта означает передачу права собственности на ресурсы с одного объекта на другой. Однако встроенные типы не содержат ресурсов, поскольку сами являются ресурсами. Нет смысла передавать ресурсы, которыми они владеют. Как показано в примере, значение num изменяется. Его ресурс, его «я» — это то, что модифицируется.

Есть ли у встроенных типов семантика перемещения?

Кроме того, имеют ли объекты встроенного типа после перемещения (если это так) четко определенное поведение?


person Mark Garcia    schedule 04.02.2013    source источник
comment
Согласно чему? ›› Перемещение объекта означает передачу права собственности на ресурсы с одного объекта на другой. Это может оставить исходный (исходный) объект в неопределенном состоянии, где присваивание может быть единственной безопасной и допустимой операцией, которую можно использовать в этом объекте. Любые операции, считывающие содержимое этих объектов, могут возвращать неопределенные значения.   -  person Nawaz    schedule 04.02.2013
comment
@Nawaz Согласно тому, что я прочитал в SO.   -  person Mark Garcia    schedule 04.02.2013
comment
std::move не двигается. В вашем примере нет ни одного перехода между выходами.   -  person R. Martinho Fernandes    schedule 04.02.2013
comment
@Mark: Разве это не зависит от вашей реализации семантики перемещения?   -  person Nawaz    schedule 04.02.2013
comment
@Nawaz Я совершил ошибку, разместив эти предположения в своем исходном посте. Я отредактировал сообщение, но теперь у меня другой, но все же тесно связанный вопрос.   -  person Mark Garcia    schedule 04.02.2013
comment
@R.MartinhoFernandes См. ^^^^^^^^^^^^^^^^^ .   -  person Mark Garcia    schedule 04.02.2013
comment
ответы на часто задаваемые вопросы. Соответствующие цитаты: std::move(some_lvalue) приводит lvalue к rvalue, тем самым разрешая последующее перемещение. и Перемещение выполняется исключительно конструктором перемещения, а не std::move, и не просто привязывая rvalue к ссылке rvalue.   -  person fredoverflow    schedule 04.02.2013


Ответы (1)


Итак, является ли то, что показано в примере, вполне определенным поведением?

Да, поведение, показанное в примере, является единственным поведением, разрешенным стандартом. Это потому, что std::move не двигается. Перемещаются конструкторы перемещения и операторы присваивания перемещения.

Все, что делает std::move, — это изменяет lvalue на xvalue, чтобы он мог связываться со ссылками на rvalue. Он не вызывает никакого конструктора или чего-либо еще. Изменение категории значения происходит на уровне типа. Ничего не происходит во время выполнения.

Ссылки Rvalue остаются ссылками: они относятся к исходному объекту. Функция увеличивает исходное целое число по заданной ссылке.

Если функция принимает аргумент по ссылке, не происходит ни копирования, ни перемещения: исходный объект привязывается к ссылке.

Если функция принимает аргумент по значению, то у нас может быть ход.

Однако фундаментальные типы не имеют конструкторов перемещения. В этом случае ходы деградируют до копий.

person R. Martinho Fernandes    schedule 04.02.2013
comment
Если функция принимает аргумент по ссылке, не происходит ни копирования, ни перемещения: исходный объект привязывается к ссылке. Если функция принимает аргумент по значению, то у нас может быть ход. Я в замешательстве - кажется, с точностью до наоборот. Если мы передаем по значению, то исходный объект изменить нельзя, так как мы просто работаем с копией. Если мы передаем по ссылке, то МОЖЕМ двигаться: см. первый пример на этой странице. learncpp.com/cpp-tutorial/15-4-stdmove Я уверен, что я просто как-то неправильно вас понимаю. - person Eric Auld; 16.04.2019
comment
@EricAuld Если вы берете аргумент по значению, параметр может быть перемещен из параметра. Таким образом, исходный объект может измениться. Если вы берете аргумент по ссылке, в процессе передачи аргумента нет движения. Другое дело, если вы переместите его позже. - person L. F.; 22.07.2019