переместить семантику и время жизни переменных при привязке ссылки lvalue к rvalues

просто чтобы хорошо понимать, что там под капотом... вопросы в коде в виде комментариев

   void test(int && val)
    {
        val=4;
    }//val is  destroyed here ?

int main()
{  
    int nb;
    test(std::move(nb));
    //undefined behavior if I reference here nb ?
    std::cout << nb;
    nb=5;
    std::cin.ignore();    
}

person Guillaume07    schedule 28.07.2011    source источник


Ответы (6)


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

person Puppy    schedule 28.07.2011

Вы должны понимать, что ссылка rvalue на что-то не волшебным образом перемещает значение. Все, что он делает, это позволяет использовать неконстантную ссылку на временные объекты.

Эта ссылка в вашем примере не отличается от обычной ссылки, потому что здесь нет временных ссылок. Вы тот, кто должен сделать «движение».

Например. если вы определяете, что ваш int пуст, когда он имеет значение 0, и вы пишете функцию, которая принимает ссылку rvalue, использует ее и устанавливает переданное значение в 0, то вы «переместили» предыдущее значение из вашего int. После вызова этой функции он будет содержать 0. Но это потому, что вы определили это именно так.

Теперь, для целых чисел это не имеет особого смысла, но представьте, что вы работаете с указателем на большой кусок памяти.

person Fozi    schedule 28.07.2011
comment
Вы должны понимать, что ссылка rvalue на что-то не волшебным образом перемещает значение, да, действительно - person Guillaume07; 29.07.2011
comment
@Guillaume Прошу прощения, если я недооценил ваш опыт, но ваш вопрос здесь уничтожен? не имеет большого смысла для меня. Val является ссылкой, так что да, ссылка val уничтожается в этот момент, но переменная, на которую ссылается val, продолжает существовать либо до тех пор, пока она не выйдет из области действия для переменных, либо до ; выражения, в котором она была создана для временных. - person Fozi; 29.07.2011

Это не неопределенное поведение, потому что вы никогда не переходите от val внутри своей функции. std::move просто превращает nb в rvalue. На самом деле это имеет смысл только тогда, когда у вас есть неоднозначные перегрузки test.

person Björn Pollex    schedule 28.07.2011

//val is  destroy here ?

Тот же ответ, как если бы тип параметра был const int& val.

//undefined behavior if I reference here nb ?

Нет. Однако распечатываемое значение не указывается. Это отличается от «неопределенного поведения», которое означает, что может произойти что угодно. Если бы это было неопределенное поведение, это означало бы, что ваш диск может быть переформатирован.

person Howard Hinnant    schedule 28.07.2011
comment
Можете ли вы объяснить, почему напечатанное значение не указано в этом случае? Я ожидал, что это будет хорошо определено, поскольку внутри функции не выполняется фактическая операция перемещения. - person Björn Pollex; 29.07.2011
comment
Я считаю, что это поведение действительно хорошо определено; он устанавливает nb равным четырем. Однако я могу ошибаться в этом, поэтому можете ли вы пояснить, почему оно будет иметь неопределенное значение? - person templatetypedef; 29.07.2011
comment
Я, видимо, иначе интерпретировал вопрос. Если вы не выполняете анализ всей программы, то значение перемещаемого объекта не указывается. В данном случае я намеренно проигнорировал определение test() при анализе main. - person Howard Hinnant; 29.07.2011

В основном ссылки на rvalue полезны, когда вы пишете новый класс, когда вас волнует стоимость его копирования, и вы хотите написать конструктор перемещения.

Использование чужого конструктора перемещения (при условии, что он хорошо спроектирован) будет практически незаметным для вас.

например Когда будет добавлено конструктор перемещения и оператор присваивания перемещения действительно имеют значение?

Поэтому, если вы хотите изучить семантику перемещения, я предлагаю вам создать пример кода с помощью конструктора перемещения.

person KarlM    schedule 28.07.2011

Хорошее объяснение std::move см. здесь. Если вы не начнете использовать конструктор перемещения, вы не сможете эффективно использовать эту новую функцию. Кроме того, я не думаю, что это имеет смысл для примитивных типов, где копирование не требует дополнительных затрат.

person jmishra    schedule 28.07.2011