10

このようにテンプレート化された関数を書くことができます

template<class T> void f(T x) {…}

またはこの方法

template<class T> void f(T const& x) {…}

明示的にコピーを回避するため、2 番目のオプションの方が最適であると思いますが、特定のタイプT(ファンクターなど) では失敗する可能性があると思います。では、いつ最初のオプションを使用し、いつ 2 番目のオプションを使用する必要があるのでしょうか? 前回の質問の回答にもありboost::call_traits<T>::param_typeましたが、どこでも使っているわけではありませんよね?これには経験則がありますか?ありがとう。boost::reference_wrapper

4

5 に答える 5

13

これには経験則がありますか?

参照渡しと値渡しをいつ使用するかについては、同じ一般規則が適用されます。

T常に数値型またはコピーするのが非常に安価な型であると予想される場合は、引数を値で取得できます。とにかく関数内のローカル変数に引数のコピーを作成する場合は、実際には作成する必要のないコピーをコンパイラが除外できるように、それを値で取得する必要があります。

それ以外の場合は、参照によって引数を取ります。コピーが安価な型の場合、コストが高くなる可能性がありますが、他の型の場合は高速になります。これがパフォーマンスのホットスポットであることがわかった場合は、さまざまなタイプの引数に対して関数をオーバーロードし、それぞれに対して正しいことを行うことができます。

于 2011-02-02T16:20:41.083 に答える
7

特定のタイプでも失敗する可能性があると思います

const への参照による受け渡しは、「決して」失敗しない唯一の受け渡しメカニズムです。に要件Tを課さず、左辺値と右辺値の両方を引数として受け入れ、暗黙的な変換を許可します。

于 2011-02-02T16:46:33.463 に答える
5

Thou shalt not wake the dead, but head to a similar problem. C++11 の型特性を使用してパラメーターを値または参照で渡す必要があるかどうかを推測する方法を示すサンプル コードを次に示します。

#include <iostream>
#include <type_traits>

template<typename key_type>
class example
{
    using parameter_type = typename std::conditional<std::is_fundamental<key_type>::value, key_type, key_type&>::type;

 public:
  void function(parameter_type param)
  {
      if (std::is_reference<parameter_type>::value)
      {
          std::cout << "passed by reference" << std::endl;
      } else {
          std::cout << "passed by value" << std::endl;
      }
  }
};

struct non_fundamental_type
{
    int one;
    char * two;
};

int main()
{
  int one = 1;
  non_fundamental_type nft;

  example<int>().function(one);
  example<non_fundamental_type>().function(nft);

  return 0;
}

同様の問題を抱えている他の人に役立つことを願っています。

于 2015-01-22T10:01:29.970 に答える
0

boost::traitsT に基づいて「最適な」型を選択する型特性があります。

call_traits<T>::param_type

既に述べたように、テンプレート固有の問題はありません。

于 2011-02-02T16:37:06.057 に答える
0

James McNellis が書いたことに加えて、テンプレートを参照型に特化できることを追加したいだけです (たとえば、このように)

于 2011-02-02T16:28:11.860 に答える