Передача по rvalue не уничтожает объект - PullRequest
0 голосов
/ 14 апреля 2019

Я немного новичок в перемещении семантики в C ++ и пытаюсь понять ее лучше. Я наткнулся на некоторый код, в котором функция переводит значение в тип только для перемещения (unique_ptr). Поэтому я решил поэкспериментировать для себя.

Я определил функцию, которая принимает в качестве параметра rvalue для unique_ptr следующим образом:

void print(std::unique_ptr<Car>&& car)
{
    std::cout << "Car" << car->Get() << std::endl;
}

Класс Car - это простой класс:

class Car
{
public:
    Car(int i) : N(i) { std::cout << "Car" << N << std::endl; }
    ~Car() { std::cout << "~Car" << N << std::endl; }

    int Get() { return N;  }

private:
    int N;
};

Теперь, если я вызову функцию следующим образом:

std::unique_ptr<Car> car = std::make_unique<Car>(99);
print(std::move(car));

Я считаю, что автомобильный объект не разрушается после вызова функции print (). Приведение к значению r не вызывает конструктор перемещения в этом случае.

Однако, если я изменю определение своей функции следующим образом:

void print(std::unique_ptr<Car> car)
{
    std::cout << "Car" << car->Get() << std::endl;
}

Тогда автомобильный объект больше не действителен после вызова print (). Параметр print () является правильным параметром приемника.

Это довольно интересно, поскольку все, что я прочитал, говорит о том, что вы должны ожидать, что объект будет уничтожен после использования std :: move - т.е. его внутренние ресурсы больше не действительны.

Буду благодарен за лучшее объяснение.

1 Ответ

0 голосов
/ 14 апреля 2019

Итак, первое, что нужно запомнить, это то, что std::move названо неправильно.Он никогда ничего не двигает.Это просто позволяет перемещать объект, заключая его в специальный вид ссылки.

«Конструктор перемещения» - это то, что выполняет фактическое перемещение.std::unique_ptr<T>(std::unique_ptr &&ref), например.

Параметры функции создаются или копируются с предпочтением для построения перемещения.

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

Второй делает правильный ход, и после вызова car будет nullptr внутри уникального ptr.И car будет уничтожен в конце print.

...