Consider the following code:
LargeObject getLargeObject()
{
LargeObject glo;
// do some initialization stuff with glo
return glo;
}
void test()
{
LargeObject tlo = getLargeObject();
// do sth. with tlo;
}
A simple compiler would create a local LargeObject glo on the getLargeObject() stack and then assign it to tlo in test() when returning, which involves a copy operation.
But shouldn’t a clever compiler realize that glo is going to be assigned to tlo and thus just use tlo’s memory in the first place to avoid the copy operation? Resulting in something (functionally) like:
void getLargeObject(LargeObject &lo)
{
// do init stuff
}
void test()
{
LargeObject lo;
getLargeObject(lo);
}
My guess is, that compilers do something similar. But can it always be done? Are there situations where it can’t be optimized like that? How can I know if my return value is copied or not?
Your guess is correct. And yes, there are situations where it cannot be done, for example:
It can’t be done there because the compiler can’t know whether it will use glo1 or glo2 for the return value.
“How can I know if my return value is copied or not?”
Two ways I can think of. You could create noisy copy constructors. That is, copy constructors that have some detectable side effect, like printing a message. Then of course there’s the old look at the assembly.