Returning a local variable as a copy - how it works

Given the sample program below, retlocal1 works, but retlocal2 does not. I know the rule that I don’t return a link or pointer to a local variable, but I was wondering how this works.

When retlocal1 returns, does it copy its value to EAX? But is EAX a register with enough space to hold an integer? So, how does EAX store the entire copy of std :: string (which can, of course, be a long, long string).

Something must be happening under the hood, which I don't understand?

This example is C ++, but I assume that C works in exactly the same way?

#include <string> std::string retlocal1() { std::string s; s.append(3, 'A'); return s; } std::string& retlocal2() { std::string s; s.append(3, 'A'); return s; } int main(int argc, char* argv[]){ std::string d = retlocal1(); std::string e = retlocal2(); return 0; } 
+4
source share
3 answers

When retlocal1 returns, does it copy its value to EAX? But is EAX a register with enough space to hold an integer? So, how does EAX store the entire copy of std :: string (which can, of course, be a long, long string).

This is not true. You should check the ABI for your platform, but the most common approach is that the calling convention for functions returning objects of a large (larger than case) transforms the function into a function that accepts an implicit pointer to the returned object. The caller allocates space for std::string , and the return statement is converted to a copy construct in this place:

 // Transformed function (with no NRVO) void retlocal(std::string *ret) { std::string s; s.append(3, 'A'); new (ret) std::string(s); return; } 

The compiler for this particular case will apply Name Returns Optimization, which will remove the s object and build instead of the returned object, avoiding copying:

 void retlocal(std::string *ret) { new (ret) std::string(); ret->append(3,'A'); return; } 
+2
source

The calling convention specifies how to return values ​​that are too large for a single register. Small types can be returned in several registers; large types, passing a "hidden" argument to the function pointer, indicating where the return value should be placed.

If you want to know all the details of gory, Wikipedia is a good starting point.

+6
source

Something must be happening under the hood, which I don't understand?

Exist.

retlocal2 returns a link to a local object, which is undefined behavior (that is, the object goes out of scope and is destroyed, then you return an invalid reference to the calling code).

retlocal1 returns a movable temporary object (reference to r-value).

You will need to ask more specific questions if you want a more accurate answer (don’t know that you don’t understand :)).

0
source

All Articles