Returning a Reference to a Local or Temporary Variable

Returning reference to local temporary object

Since you're not in control of the return type, you must make sure you return a valid object and not just a temporary. One solution would be a function-local static variable:

virtual const core::matrix4& getViewMatrixAffector() const
{
static const core::matrix4 val;
return val;
};

If you find yourself doing this in many functions (with the same type of the variable), make val a (suitably renamed) static member of the class.

Returning a reference to a local or temporary variable

You got lucky. Returning from the function doesn't immediately wipe the stack frame you just exited.

BTW, how did you confirm that you got a 6 back? The expression std::cout << &i ... prints the address of i, not its value.

C++ Returning reference to local variable

This code snippet:

int& func1()
{
int i;
i = 1;
return i;
}

will not work because you're returning an alias (a reference) to an object with a lifetime limited to the scope of the function call. That means once func1() returns, int i dies, making the reference returned from the function worthless because it now refers to an object that doesn't exist.

int main()
{
int& p = func1();
/* p is garbage */
}

The second version does work because the variable is allocated on the free store, which is not bound to the lifetime of the function call. However, you are responsible for deleteing the allocated int.

int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}

int main()
{
int* p = func2();
/* pointee still exists */
delete p; // get rid of it
}

Typically you would wrap the pointer in some RAII class and/or a factory function so you don't have to delete it yourself.

In either case, you can just return the value itself (although I realize the example you provided was probably contrived):

int func3()
{
return 1;
}

int main()
{
int v = func3();
// do whatever you want with the returned value
}

Note that it's perfectly fine to return big objects the same way func3() returns primitive values because just about every compiler nowadays implements some form of return value optimization:

class big_object 
{
public:
big_object(/* constructor arguments */);
~big_object();
big_object(const big_object& rhs);
big_object& operator=(const big_object& rhs);
/* public methods */
private:
/* data members */
};

big_object func4()
{
return big_object(/* constructor arguments */);
}

int main()
{
// no copy is actually made, if your compiler supports RVO
big_object o = func4();
}

Interestingly, binding a temporary to a const reference is perfectly legal C++.

int main()
{
// This works! The returned temporary will last as long as the reference exists
const big_object& o = func4();
// This does *not* work! It's not legal C++ because reference is not const.
// big_object& o = func4();
}

C++ compiler warning - returning local variable

You can't return a reference to a local variable. Inside the operator+() function, you're creating a local variable called tmp. It will get destroyed as soon as the function exits. You can't return a reference to that variable, because it no longer exists when the calling function gets the return value.

Change your definition of the function to:

const Int operator+(const Int&) const;

It would build without warnings and work fine too.

return const reference vs temporary object

Even if you assign it to a const reference, the return value is declared as passed by value, that means it'll be copied[1] to outside as a temporary object, and then binded to the const reference. Binding temporary object to a const reference is fine, the object won't be destroyed until getting out of the lifetime of the const reference.

On the other hand, returning reference of a local variable is illegel. The local variable'll be destroyed when the function returned, that means the outside reference will be dangled.

EDIT

My point is that if assigning a const ref to a returned local variable is legal, then shouldn't assigning a const ref to a returned const ref of a local variable be legal as well?

The point is the 1st case is not assigning a const ref to a returned local variable, it's assigning a const ref to a returned temporary variable. (Which might copied from the local variable.)


[1] The copy might be omitted according to RVO technically.

Warning: returning reference to local temporary object

No, "returning a reference" does not magically extend any lifetime.

The only time that lifetime is extended is when a prvalue (or an xvalue referring to a member of a prvalue) is bound to a reference variable, and the lifetime of the prvalue is extended to that of the variable:

struct Foo{};

{
const auto & r = Foo{}; // Foo object not destroyed at semicolon...
// ...
}
// ... but is destroyed only here.

Your prvalue is not bound to any variable, and hence no lifetime is extended.

(Also note that non-static class data members don't count as "variables" for this consideration, so you also can't extend lifetimes via constructor initializer lists if your class happens to have reference members.)

Why I get the following error: returning reference to temporary [-Werror=return-local-addr]

The set<...>::begin function returns its iterator by value. Since you do not store that value anywhere, it's a temporary value, and you can't really have references to temporary values.

The simple solution is for your function to also return by (non-const) value.



Related Topics



Leave a reply



Submit