3

C/C++ で構造体を値渡しする場合、構造体の内容をコピーする必要があります。コンパイラはどのようにそれを達成しますか? つまり、通常、このコピーに対して発行されるアセンブリ命令はどれですか?

たとえば、memcpy の呼び出しと比較して、これらはどれくらい速いですか?

次のコードを検討してください。

struct X { int i, j, k; };

void foo(X x);

void foo( int i, int j, int k);

foo(X) と foo(int,int,int) の呼び出しに違いはありますか、それとも生成されたアセンブリ コードは同じでしょうか (パラメーターの受け渡しを考慮して)?

4

4 に答える 4

6

C++ の場合

コンパイラはどのようにそれを達成しますか?

そのクラス/構造体のコピー コンストラクターを呼び出します。提供しない場合は暗黙的に生成されたもの、または提供したもの。

たとえば、への呼び出しと比較して、これらはどれくらい速いmemcpyですか?

クラスとそのメンバーによって異なります。プロファイリングにより、より明確な全体像が得られるはずです。
ただし、memcpyクラス インスタンスのコピーには使用しないでください。

Cで

コンパイラはどのようにそれを達成しますか?

その構造の浅いコピーを実行します。すべての実用的な目的で、 と同じと見なすことができますmemcpy

于 2013-02-15T11:26:28.203 に答える
4

明らかに、structorのコンストラクターがあるclass場合、コンストラクターが呼び出されます。

コンストラクターがない場合、それは完全にコンパイラ次第ですが、ほとんどの場合、3 つの整数サイズのオブジェクトの場合、おそらく 3 つの個別のmov命令になります。より大きな構造の場合は、 への呼び出しか、 のようmemcpyなインライン バージョンmemcpyです。

また、構造が非常に大きい (数メガバイト) 場合、その truememcpyはインライン バージョンよりも高速である可能性が高く、コンパイラはこれを認識せず、とにかくインライン バージョンを使用する可能性があります。しかし、私たちのほとんどはメガバイトの大きな構造体を使用していないので、一般的にはあまり心配する必要はないと思います。構造体が数メガバイトのサイズである場合、構造体を引数としてスタックにコピーすることは、典型的なスタックの制限されたサイズを考えると、おそらく最初から良い考えではありません。

于 2013-02-15T11:34:31.810 に答える
3

2つの異なるケースがあります。

  • 構造体がPODの場合、コピーは最適化され、memcpy と同じくらい高速になります (適切な最適化レベルで)。

  • 構造体がPOD でない場合、C++ はオブジェクトのコピー コンストラクターを呼び出す必要があります。コピー コンストラクターは、他の関数、新しい演算子などを呼び出す可能性があるため、memcpy よりも遅くなります。ただしmemcpy、構造体の修正はコピーされません。PODmemcpy以外の型で使用すると、未定義の動作が発生します。

たとえば、g++への呼び出しでmemcpyはインライン化され、最適化されることに注意してください。構造体のコピーと memcpy 呼び出しの意図はまったく同じ (位置 Y から Z に X バイトをコピーする) ため、生成されるアセンブリ コードに違いはないと思います。

とにかく、確かに、コードのアセンブリを分析して見つけてください。


編集:関数パラメータに関する質問の最後を読んでください。関数パラメーターの受け渡しは通常 (特に x64 では) レジスターで行われ、 よりもはるかに高速であることに注意してくださいmemcpy

アセンブリ コードを確認しましたが、それらは異なります。正確なコードは、現在のコンパイラが使用する呼び出し規約によって異なります。私にとって、構造体はレジスタに渡されるのではなく、スタックに渡され、実際のコピーが作成されます。3 つのintが渡され%ecxます。Windows GCCでこれを試しました。Windows x64 呼び出し規約を使用しているようです。%edx%r8d

パラメータがどのように渡されるかについての詳細は、呼び出し規約の仕様を参照してください。すべての詳細とコーナーケースが解決されました。たとえば、x64 GCC については、System V AMD64 ABI Chapter 3.2.3 パラメータの受け渡しを参照してください。Visual Studio については、こちらをご覧ください。

于 2013-02-15T11:35:07.153 に答える
0

Alok Save for による別の回答を参照してください。では、それはmemcpy(または同等のもの)またはインラインバージョン(mov適切なサイズの構造体の最大1つの命令)にすることができます。

于 2013-02-15T11:28:30.563 に答える