0

I made a method that returns an object in that way:

MyObject && 
MyController::getMyObject (const otherObject & options) const
{
    MyObject tmp;

    tmp.doSometing(options);

    return std::move(tmp);
}

Later in my code, I wanted to use that method with chained calls like this :

controller.getMyObject(options).doAnotherThing();

And it doesn't work, the call to "doAnotherThing" relies on an empty object. I know how to fix the situation :

auto tmp = controller.getMyObject(options);

tmp.doAnOtherThing();

My questions are : In the first place, is the method written correctly ? How can I avoid to write the second way for the usage ? It's really ulgy...

Note: "MyObject" is movable.

Biffen
  • 6,249
  • 6
  • 28
  • 36
  • 2
    Basically a dupe of [this](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope). TL;DR: **Never** return a pointer or reference to a non-static function local variable. – NathanOliver Oct 23 '18 at 13:16
  • 3
    have a look at this [question](https://stackoverflow.com/questions/4986673/c11-rvalues-and-move-semantics-confusion-return-statement) – Michiel uit het Broek Oct 23 '18 at 13:18

2 Answers2

2

In the first place, is the method written correctly ?

Nope. You return a reference to an object that has gone out-of-scope.

How can I avoid to write the second way for the usage ?

Return by value.

MyObject 
MyController::getMyObject (const otherObject & options) const
{
    MyObject tmp;

    tmp.doSometing(options);

    return tmp;
}

The above will behave in one of two ways due to how N/RVO is setup in C++. Either tmp will be elided and getMyObject operates on the result object directly. Or the result object is constructed by moving tmp. Either way, you get a valid object to use for method chaining.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
2

In the first place, is the method written correctly ?

No. The function returns a dangling reference.

Both the first and the second usages have undefined behaviour.

A correct way, and probably what you inteded is to return an object, rather than a reference:

MyObject
MyController::getMyObject (const otherObject & options) const
{
    MyObject tmp;
    tmp.doSometing(options);
    return tmp;
}
eerorika
  • 232,697
  • 12
  • 197
  • 326