开发者

C++: What are R-Value references on a technical level (ASM)? [duplicate]

开发者 https://www.devze.com 2023-04-10 01:11 出处:网络
This question already has answers here: Closed 11 years ago. Possible Duplicate: What is the difference between r-value references and l-value references? (CodeGen)
This question already has answers here: Closed 11 years ago.

Possible Duplicate:

What is the difference between r-value references and l-value references? (CodeGen)

I was wondering, can anyone explain what R-Value references are on a technical level? By that I mean: What happens on assembler level when R-Value references are created.

For a small test to see what happens inside I wrote the following code:

char c = 255;
char &c2 = c;
char &c3 = std::move(c);

I know it makes no sense to create a R-Value reference to 'c', but just for the sake of testing I did it anyway, to see what it does. And here's the result:

unsigned char c = 255;
    mov         byte ptr [c],0FFh
unsigned char &c2 = c;
    lea         eax,[c]  
    mov         dword ptr [c2],eax 
unsigned char &&c3 = std::move(c);
    lea         eax,[c]  
    push        eax  
    call        std::move<unsigned char &> (0ED1235h)  
    add         esp,4  
    mov         dword ptr [c3],eax

I am by far no asm expert but it looks to me that, in this case, 'c3' is a regular reference to 'c' in the end.

If I bind the R-Value reference directly to a temporary (char &&c3 = 255), the last bit of assembler changes as such:

unsigned char &&c3 = 255;
    mov         byte ptr [ebp-29h],0FFh  
    lea         eax,[ebp-29h]  
    mov         dword ptr [c3],eax

From the looks of this change, I assume that c3 still actually is a reference to some memory location which holds the value 255. So it's a regular reference - the value is not copied/assigned to c3. Is this true?

Can anyone say if my assumptions are correct or if I am totally off the track? Until now I always thought of R-Value references to match a functions/methods signature (possibly a move-ctor) when it comes to calling resolution, so that the coder knows how to treat th开发者_开发百科e data that is provided (for a move-ctor that would be moving the data instead of copying it).

To defend this rather stupid attempt I just presented: I don't intend to screw around with my code on asm level, I just want to unterstand what technical differences R-Value references introduced compared to the rest that has been around all these years.

Any insights and explanations are more than welcome!

Thanks!


What happens on assembler level when R-Value references are created.

Whatever is needed to preserve high-level semantics. What compiler does exactly depends on what compiler vendor thought would be a good idea. Assembly has no concept of lvalues, rvalues, or references, so stop looking for them. Turn on the optimisations, and the code you're looking at will probably change (or might stop existing at all, if the variables are not used).

I just want to unterstand what technical differences R-Value references introduced compared to the rest that has been around all these years.

Rvalue references enable move semantics, and those in turn enables important optimisation opportunities. The standard doesn't say "oh, these are rvalue refs, and that's how you should implement them in assembly". Implementation might not even produce assembly, at all.


Rvalue reference is not different on asm level - it could be exactly the same as regular refernces (depends on how compiler sees it though). The difference exists only on C++ langiage level. Information r-value reference is carrying is that referenced object is temporary, and anyone recieving it is free to modify it. Information about object location might be transfered exactly the same as with regular references (compiler might try to optimize it differently, but that's compiler's internal matter).

The difference between r-value refernce and non-const l-value reference is that every l-value will be automatically casted only to l-value reference (thus preventing accidental modifications), while r-value'd expressions will convert to both (with r-value ref. preffered), allowing move semantics and regular calls if move semantics is unsupported. std::move is doing nothing else than allowing non-automatic casting of l-values into r-values references.


Before optimization, a reference exists as a pointer containing the address of the bound object.

But the compiler tries very hard to optimize it away. Inlining especially may cause all use of a reference parameter inside a small function to be replaced by direct use of a register which contains the value of the bound object.


rvalue reference concept can be completely described on C++ level, there is no need to read Assembly code for this. You just need to get some minimal C++ class which allocates internal resources, and "stealing" rvalue reference resources by another object is obvious. Like in remote_integer class from this classic article: http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx Assembly translation for this code is pretty straightforward, but the difference is seen in C++ code. Regarding simple types like char - they can be used to demostrate some rvalue reference syntax features, but there is no sence to use rvalue references on such type - both on C++ and Assembly level. So, if you don't see any advantage in using char &&c in C++, there is nothing interesting also in Assembly.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号