大きなループの最中に、コード内で多くのポインターを渡す必要があります (そのため、 のような式がたくさんありますfoo(&x, &y, ...)
)。パフォーマンスのためにポインタを別の変数(つまりキャッシュ)として格納する必要があるかどうか疑問に思っていました (より多くの変数を導入し、コードを混乱させるという犠牲を払って)。
(多くの行列 mult を実行し、CUBLAS ライブラリはポインターを主張します...)
大きなループの最中に、コード内で多くのポインターを渡す必要があります (そのため、 のような式がたくさんありますfoo(&x, &y, ...)
)。パフォーマンスのためにポインタを別の変数(つまりキャッシュ)として格納する必要があるかどうか疑問に思っていました (より多くの変数を導入し、コードを混乱させるという犠牲を払って)。
(多くの行列 mult を実行し、CUBLAS ライブラリはポインターを主張します...)
いいえ -- address-of 演算子は、期待できるものとほぼ同じくらい安価/高速です。オーバーロードすることは可能であり、そのようなオーバーロードは遅くなる可能性がありますが、オーバーロードすることはまったく珍しいことです。
std::addressof
ペナルティは一切かかりません。アセンブリ コードに要約すると、いずれにせよアドレスを介してのみオブジェクトを参照するため、情報は既に手元にあります。
に関してoperator&
は、オーバーロードされているかどうかによって異なります。オーバーロードされていない元のバージョンは、 とまったく同じように動作しstd::addressof
ます。ただし、operator&
がオーバーロードされている場合 (これはとにかく非常に悪い考えであり、非常に眉をひそめています)、オーバーロードされた実装がどうなるかを推測できないため、すべての賭けはオフです。
したがって、あなたの質問に対する答えは次のとおりです。ポインターを個別に保存する必要はありません。繰り返しが必要な場合でも、必要なときにいつでもstd::addressof
orを使用できます。operator&
C++ には参照があります。あなたが説明していることは、C++ ではなく C 言語の動作のように聞こえます。
C++ メソッドのその種の署名は、通常、コピーを回避するために実装されます。デフォルトでは、メソッドを呼び出していくつかの引数を渡すと、この引数はローカル コピーを生成し、参照を持ちます。これは、コピーのオーバーヘッドを回避するのに役立つ手法です。
それは非常に効率的です。Linux を使用している場合は、objdump を使用して確認できます。以下は、x86 アーキテクチャで fooP(&var1, &var2) がどのように見えるかです。それはLEA命令にすぎません。
fooP(&var1, &var2);
8048642: 8d 44 24 1c lea 0x1c(%esp),%eax -> this is to get the address of var2 to eax
8048646: 89 44 24 04 mov %eax,0x4(%esp) -> this is to save the address to the stack for later fooP call
804864a: 8d 44 24 18 lea 0x18(%esp),%eax -> address of var1
804864e: 89 04 24 mov %eax,(%esp)
8048651: e8 be ff ff ff call 8048614 <_Z4fooPPiS_>
この場合の参照は、実際には上記と同じです。