Какой смысл передавать rvalue ссылку на конструктор класса? - PullRequest
1 голос
/ 28 апреля 2020

ОК

Итак, у меня есть класс, MyClass. Я хотел бы построить этот класс, скажем, с вектором целых. Я хочу переместить этот вектор в объект. Класс не является шаблонным.

class Myclass {
     public:
     Myclass (std::vector<int> && in) : vec{in} {};
     Myclass (std::vector<int> & in) : vec{in} {};

    private:
    std::vector<int> vec;
    }

В моем основном у меня есть

std::vector<int> orig (100);
Myclass A {orig};
std::cout << A.size() << '\n';

Я хочу, чтобы значение "orig" было пустым после перемещения его в "A". Этого не происходит ни в одном из вариантов выше. Даже если я сделаю

    std::vector<int> orig (100);
    Myclass A {std::move(orig)};
    std::cout << A.size() << '\n';  // still prints 100

Похоже, я смогу добиться этого через

 Myclass (std::vector<int> && in) : vec{std::move(in)} {};   // (1)

ИЛИ

 Myclass (std::vector<int> & in) : vec{std::move(in)} {};    // (2)

ИЛИ

Myclass (std::vector<int> && in) : vec{std::forward<std::vector<int>(in)} {};    // (3)

Мой вопрос: почему (1) ведет себя так же, как (2)?

1 Ответ

2 голосов
/ 28 апреля 2020

Помните о ссылках, rvalue и lvalue, что они являются lvalues. Это означает, что если у вас есть ссылка на вещь, эта ссылка является lvalue, и вам нужно std::move, чтобы привести ее к rvalue, чтобы ее можно было переместить.

Реальная разница между Myclass (std::vector<int> && in) и Myclass (std::vector<int> & in) в том, что с первым вы должны использовать

Myclass A {std::move(orig)};
// or
Myclass A {std::vector(100)};

и не можете передать ему lvalue, где, как и во втором, вы можете использовать только

Myclass A {orig};

, так как он не позволит вам пройти его значение.


Также обратите внимание, что конструктор 3 "неверен". Вы должны использовать std::forward, только если у вас есть ссылка для пересылки. std::vector<int> && in является ссылкой на rvalue, а не на переадресацию, поэтому вместо нее следует использовать std::move. Для правильного использования forward вам понадобится конструктор шаблона, например

template <typename T, std::enable_if_t<
                                       std::is_same<std::decay_t<T>, 
                                       std::vector<int>>, bool> = true>
Myclass (T&& in) : vec{std::forward<T>(in)} {}; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...