Уникальные указатели: вызов функции LValue или вызов функции RValue Reference - PullRequest
2 голосов
/ 07 апреля 2020

Я начал использовать c ++ std::unique_ptr s и наткнулся на следующую проблему:

Я хочу передать ссылку на свой уникальный указатель на функцию и назначить новое значение указателю в этой функции. Интуитивно, я думаю, что функция должна принимать ссылку lvalue, чтобы иметь возможность изменять указатель. Но в следующем примере кода оба параметра (lvalue reference и rvalue reference + std::move) делают одно и то же (я полагаю).

#include <memory>
#include <utility>

struct Widget {
    Widget(int) {}
};

void reseat_RValue(std::unique_ptr<Widget>&& uniqPtr) {
    auto tempUniqPtr = std::make_unique<Widget>(2003);
    uniqPtr = std::move(tempUniqPtr);
}

void reseat_LValue(std::unique_ptr<Widget>& uniqPtr) {
    auto tempUniqPtr = std::make_unique<Widget>(2010);
    uniqPtr = std::move(tempUniqPtr);
}

int main() {
    auto uniqPtr = std::make_unique<Widget>(1998);

    reseat_RValue(std::move(uniqPtr)); // (1)

    reseat_LValue(uniqPtr); // (2)   
}

Я не очень понимаю, в чем разница между (1) и (2) или, скорее, какой я должен использовать для моего варианта использования. Поэтому, возможно, кто-то мог бы объяснить, что происходит с каждой из этих функций и какую мне следует использовать.

Ответы [ 2 ]

3 голосов
/ 07 апреля 2020

Да, они делают то же самое. Исходя из вашего намерения, т. Е. Передавая по ссылке и изменяя ее в функции, лучше будет передавать по lvalue-reference. Это делает ваше намерение более ясным (как предложено @bitmask); функция ожидает значение l и изменяет его внутри функции. А для передачи по rvalue-reference вам нужно использовать std::move для lvalues, которые будут переданы функции, и это позволяет передавать rvalue, как временные значения, которые кажутся бессмысленными. например,

// meaningless; the temporary `std::unique_ptr` would be destroyed immediately
reseat_RValue(std::make_unique<Widget>(1998)); 
1 голос
/ 07 апреля 2020

На самом деле std :: unique_ptr :: reset делает то же самое для вас в функции со ссылкой на lvalue - это проще. ИМО, семантика rvalue подходит лучше всего для огромных объектов, а не для указателей. Но да, unique_ptr использует его для достижения единственного числа указателей.

...