Как правильно переместить объект из функции возврата? - PullRequest
1 голос
/ 24 апреля 2020

У меня есть объект, который не следует копировать, а только перемещать, и поэтому я попытался убедиться, что функция возвращает T&& объекта. Моя проблема в том, что объект уничтожается до его возвращения, и я не знаю, как это сделать правильно.

#include <iostream>

class Foo
{public:
    Foo() { 
        a = new int; 
        std::cout << a << '\n'; 
    }
    Foo(const Foo& other) = delete;
    Foo(Foo&& other) { 
        a = other.a; other.a = nullptr; 
    }
    ~Foo() { 
        std::cout << a << '\n';
        delete a; 
    }
    void operator= (const Foo& other) = delete;
    void operator= (Foo&& other) { 
        a = other.a; 
        other.a = nullptr; 
    }
    int* a;
};

Foo&& createNewFoo()
{
    return std::move(Foo());
}

int main()
{
    Foo foo = createNewFoo(); // The pointer is deleted before this assigns to foo

}

Ответы [ 2 ]

4 голосов
/ 24 апреля 2020

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

Изменение функции для возврата по значению было бы хорошо; Значение r будет перенесено в возвращаемое значение.

Foo createNewFoo()
{
    return Foo();
}

Кстати: для приведенного выше кода Foo foo = createNewFoo(); не будет копировать / перемещать что-либо из-за copy elision , что гарантировано с C ++ 17.

РЕДАКТИРОВАТЬ

Так почему временное уничтожение не уничтожается сразу при возврате return Foo();

Для возврата по значению порядок возврата:

  1. . Построить временное
  2. . Переместить-построить. Возвращаемое значение из временного
  3. Временное уничтожается * 1027. *

Для возврата по ссылке, порядок:

  1. , создание временного
  2. , привязка временного значения к возвращаемому значению
  3. временное уничтожение
  4. возвращаемое значение (ссылка) становится зависшим
2 голосов
/ 24 апреля 2020

Вы можете просто сделать следующее:

static Foo createNewFoo() {
    return Foo();
}

Поскольку Foo() уже является r-значением, std::move не требуется.

...