Zebrafish
Zebrafish

Reputation: 13936

How to move object from a function return correctly?

I have an Object that should not be copied, but only moved, and so I've tried to ensure that a function returns the T&& of the object. My problem is that the object is being destroyed before it returns and I don't know how to do this properly.

#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

}

Upvotes: 1

Views: 810

Answers (2)

NutCracker
NutCracker

Reputation: 12263

You can just do the following:

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

Since Foo() is already an r-value, no std::move is needed.

Upvotes: 2

songyuanyao
songyuanyao

Reputation: 172934

You're constructing a temporary object and binding it to the rvalue-reference as the return value, the temporary will be destroyed after the full expression immediately then the returned reference is always dangled.

Changing the function to return-by-value would be fine; rvalue would be moved to the return value.

Foo createNewFoo()
{
    return Foo();
}

BTW: For the above code, Foo foo = createNewFoo(); won't copy/move anything due to copy elision, which is guaranteed since C++17.

EDIT

So why isn't the temporary destroyed immediately when returning return Foo();

For return-by-value, the order of returning is

  1. construct the temporary
  2. move-construct the return value from the temporary
  3. temporary gets destroyed

For return-by-reference, the order is

  1. construct the temporary
  2. bind the temporary to return value
  3. temporary gets destroyed
  4. return value (the reference) becomes dangled

Upvotes: 4

Related Questions