3

一言で言えば、ポインターを値で渡すのと const の参照で渡すのとではどちらが良いでしょうか?

探索する簡単な関数を作成しました。

void foo(int* v) { std::cout << *v << endl; }

void foo(int* const& v) { std::cout << *v << endl; }

生成されたアセンブリを見てみましたが、特にアセンブリが得意ではないので違いがよくわかりません。しかし、違いがあります。最初のケースでは、次のようになります。

pushq   %rbp
pushq   %rbx
subq    $8, %rsp
movl    (%rdi), %esi
movl    std::cout, %edi
call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)

このconst&場合、もう 1 つの操作を取得します。

pushq   %rbp
pushq   %rbx
subq    $8, %rsp
movq    (%rdi), %rax
movl    std::cout, %edi
movl    (%rax), %esi
call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)

その違いは何を意味し ( mov2 つではなく 3 つ)、その意味は何ですか? (基本的に、私は生のポインターであるかどうかにかかわらず構造体を持っており、Foo<T>代わりにT関数を . にする必要があるかどうか疑問に思っています)。bar(const T&)bar(typename boost::call_traits<T>::type)

4

3 に答える 3

9

参照セマンティクスが必要でない限り、ポインターを値で渡します。

参照渡しは、ほぼ確実にポインターを渡すことで実装されます。ポインター自体と同じ量のデータを渡しますが、余分なレベルの間接性が導入されるため、値渡しよりも効率が低下する可能性があります。

そうは言っても、違いはごくわずかです。したがって、汎用コードの場合、単一の命令のレベルでマイクロ最適化する必要がない限り、const 参照で渡す方が簡単です。そうすれば、あなたが言うように、boost::call_traits助けることができます。

于 2013-10-31T15:22:01.273 に答える
1

ポインタを参照渡しすると、次のことが行われます。

Address: 0x00  -  42   (int)
Address: 0x11  -  0x00 (int*)
Address: 0x22  -  0x11 (int* const&)

これは基本的に、コンパイラが int* const& に対して生成するものです。実装に関しては、最終的に int** になる可能性があります。

そのため、3 行目のオーバーヘッドなしで int のアドレスを直接コピーするため、ポインターを値で渡す方が効率的になります。

于 2013-10-31T15:30:44.333 に答える
0

ポインターの場合は、値で渡します。定義上、ポインターをポインターに渡すこと (これは内部で行われます) は、ポインターを渡すことよりも効率的ではありません。アセンブラの余分な行 (私はほとんど知りません) は、実際には効率が悪いことを示唆しています。

于 2013-10-31T15:23:21.383 に答える