7

重複の可能性:
r値参照とl値参照の違いは何ですか?(CodeGen)

疑問に思っていたのですが、技術レベルでR値の参照が何であるかを誰かが説明できますか?つまり、R値参照が作成されたときにアセンブラレベルで何が起こるかということです。

内部で何が起こるかを確認するための小さなテストとして、次のコードを記述しました。

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

'c'へのR値参照を作成することは意味がないことは知っていますが、テストのために、とにかくそれが何をするかを確認するために作成しました。結果は次のとおりです。

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

私はasmの専門家ではありませんが、この場合、「c3」は最終的に「c」への通常の参照であるように見えます。

R-Value参照を一時(char && c3 = 255)に直接バインドすると、アセンブラの最後のビットは次のように変更されます。

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

この変更の外観から、c3はまだ実際には値255を保持するメモリ位置への参照であると思います。したがって、これは通常の参照です。値はc3にコピー/割り当てられません。これは本当ですか?

私の仮定が正しいのか、それとも私が完全に軌道に乗っていないのか、誰かが言うことができますか?これまで、解像度の呼び出しに関しては、関数/メソッドのシグネチャ(おそらくmove-ctor)と一致するR値参照を常に考えていたため、コーダーは(move-ctorに対して)提供されたデータの処理方法を知っています。データをコピーするのではなく移動することになります)。

私が今提示したこのかなりばかげた試みを守るために、私はasmレベルでコードをいじくり回すつもりはありません。ただ、R値参照がここ数年の残りの部分と比較してどのような技術的な違いをもたらしたかを理解したいと思います。

どんな洞察や説明も大歓迎です!

ありがとう!

4

4 に答える 4

8

R-Value 参照が作成されたときにアセンブラー レベルで何が起こるか。

高レベルのセマンティクスを維持するために必要なもの。どのコンパイラが正確に何をするかは、どのコンパイラ ベンダーが良いアイデアだと考えたかによって異なります。アセンブリには、左辺値、右辺値、または参照の概念がないため、それらを探すのはやめてください。最適化をオンにすると、見ているコードがおそらく変更されます (変数が使用されていない場合は、存在しなくなる可能性があります)。

R-Value リファレンスが導入した技術的な違いを、これまでの残りの部分と比較して理解したいだけです。

右辺値参照は移動セマンティクスを有効にし、それらは重要な最適化の機会を有効にします。標準は、「ああ、これらは右辺値参照であり、それがアセンブリでそれらを実装する方法です」とは言いません。実装によってアセンブリがまったく生成されない場合もあります。

于 2011-09-29T16:09:14.130 に答える
6

右辺値参照はasmレベルで違いはありません-通常の参照とまったく同じである可能性があります(ただし、コンパイラーがそれをどのように見るかによって異なります)。違いは、C++言語レベルでのみ存在します。r値参照が保持している情報は、参照されたオブジェクトが一時的なものであり、それを受け取った人は誰でも自由に変更できるということです。オブジェクトの場所に関する情報は、通常の参照とまったく同じように転送される場合があります(コンパイラーはそれを異なる方法で最適化しようとする場合がありますが、それはコンパイラーの内部的な問題です)。

r値参照と非定数l値参照の違いは、すべてのl値が自動的にl値参照にのみキャストされるのに対し(したがって、誤った変更を防ぐ)、r値の式は両方に変換されることです( r値参照が優先されます)、移動セマンティクスがサポートされていない場合に移動セマンティクスと通常の呼び出しを許可します。std :: moveは、l値をr値参照に非自動キャストできるようにする以外に何もしていません。

于 2011-09-29T16:21:27.330 に答える
4

最適化前は、バインドされたオブジェクトのアドレスを含むポインターとして参照が存在します。

しかし、コンパイラはそれを最適化して取り除こうと懸命に努力します。特にインライン化により、小さな関数内の参照パラメーターのすべての使用が、バインドされたオブジェクトの値を含むレジスターの直接使用に置き換えられる可能性があります。

于 2011-09-29T16:09:29.587 に答える
0

右辺値参照の概念は、C++ レベルで完全に記述できます。このためにアセンブリ コードを読む必要はありません。内部リソースを割り当てる最小限の C++ クラスを取得する必要があるだけで、別のオブジェクトによる右辺値参照リソースの「盗用」は明らかです。この古典的な記事の remote_integer クラスのように: http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx このコードのアセンブリ変換は非常に単純ですが、違いは C++ コードで見られます。char のような単純な型に関しては、いくつかの右辺値参照の構文機能を説明するために使用できますが、そのような型で右辺値参照を使用する意味はありません (C++ レベルとアセンブリ レベルの両方で)。したがって、C++ で char &&c を使用する利点が見られない場合、Assembly でも興味深いことは何もありません。

于 2011-09-29T16:27:23.503 に答える