Is this the only rule to follow when returning
by reference? To be sure that the value returned
does not go out of scope?
The reference will become invalid if the lifetime of the object you are referencing ends, so that is what you need to avoid.
Your first case is valid because a is a global variable and will be initialized before main starts, and destroyed after main ends.
Your second case doesn't compile, but if we modify to compile...
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class test {
public:
staticint a;
staticint& getRef() {
return a;
}
staticint getA() {
return a;
}
};
int test::a = 10;
Then it will also be valid, because static class variables exist for the lifetime of the program.
Note: If by "safe" you are talking about thread safety instead, then you should have locks/mutexes to ensure only one thread is ever writing the static or global variable at a time.
Okay, thanks for clearing that up.
Though I do not know what locks/mutexes are.
I do not know if I meant thread safety. If I do
understand what that is should I just not return
by reference?
Okay, forget about thread safety for now, since it will just confuse you more.
Let's just assume we're dealing with one thread.
The solution is not to avoid using references. They are useful constructs to use. The solution is to understand it, so it's good that you're asking questions.
This is bad:
1 2 3 4 5
int& foo()
{
int obj = 42;
return obj;
}
This is bad because obj is a local variable, and will be destroyed after this function exists.
Okay. So, what I understand from this is that an object and its reference must exist
for the same amount of time, or the referenced object must exist longer? I'm sorry,
I may still be a bit confused.
the object referred to must exist at the time the reference is used.
a function destroys the local, non static variables when it exits, so references to them are no longer valid if you try to use them.
wrapping them in a class or making them static or passing them into the function all provide ways around the issue. Global variables also are a way around it, but that is a poor choice.
1 2 3 4 5 6 7 8 9 10 11 12 13
int& foo()
{
staticint obj = 42; //ok: static makes obj last until program ends, not function end.
return obj;
}
int& foo(int &obj)
{
obj = 42;
return obj; //ok, it was passed into the function, so it exists somewhere else.
}
and the above class idea can be done as a functor ( a class that acts like a function by overloading () operator) as well.
for an integer, copying it is just as efficient, possibly moreso, than returning a reference anyway.