Как сохранить объект, переданный по ссылке на rvalue, без копирования? - PullRequest
0 голосов
/ 06 июля 2019

Я пытаюсь передать Child как r-значение Parent и сохранить его там без копирования Child.

Parent p{ Child{} };

cout << "----Done----" << endl;

А теперь реализация:

class Child
{
public:
    Child() { cout << "Child: created" << endl; }

    ~Child() { cout << "Child: destroyed" << endl; }
};

class Parent
{
    // store as r-value ref
    Child&& child;

public:
    // pass by r-value ref and move
    Parent(Child&& c) :child(move(c))
    {
        cout << "Parent: created" << endl;
    }

    ~Parent() { cout << "Parent: destroyed" << endl; }
};

Вывод:

Дочерний элемент: создан
Родитель: создан
Дочерний элемент: уничтожен
----- Готово ------
Родитель: уничтожен

cppref говорит: Rvalue references can be used to extend the lifetimes of temporary objects

Вопрос 1: Почему нет Child уничтожено в самом конце (или хотя бы после Готово )?
Вопрос 2: Как заставить его жить дольше?

PS:

Child& child;
...
Parent(Child c) :child(c)

Дает точно такой же результат.

Ответы [ 2 ]

1 голос
/ 06 июля 2019

cppref говорит: Rvalue references can be used to extend the lifetimes of temporary objects

Вы упускаете важную часть этой цитаты. Более точная цитата: «Rvalue ссылки могут использоваться для продления времени жизни временных объектов» .

Заметили разницу? (Не беспокойтесь слишком сильно, если это не так, потому что это не так заметно.) Существует ссылка на объяснение того, как и когда можно продлить срок службы временного. Вы пометили этот вопрос C ++ 11, поэтому пункт с маркером, действительный до C ++ 14, применяется:

  • временная привязка к элементу ссылки в списке инициализатора конструктора сохраняется только до выхода из конструктора, а не до тех пор, пока объект существует. (примечание: по состоянию на 1696 год такая инициализация неверна).

Вы связали временный элемент со ссылкой в ​​списке инициализатора конструктора. Срок службы временного не распространяется за пределы конца конструктора. Временный уничтожается до вызова деструктора вашего объекта.


Как заставить его жить дольше? Это сложно, но если параметр всегда является временным, вы можете сделать ваш элемент не ссылочным и move параметр для члена. Если вам нужна большая гибкость, вам может потребоваться некоторое копирование.

0 голосов
/ 06 июля 2019

Часть указанного вами стандарта относится к чему-то вроде:

struct A { };
int main() {
  const A &a = A{};
  ...
}

и теперь a будет уничтожено, как только закончится область действия функции main. Это не работает для учеников. Передача значения в функцию по ссылке (в конце концов, конструктор - это просто функция) не продлевает время жизни ссылки. Также не присваивается его переменной-члену.

...