3

ファンクター (状態を保持する関数) を作成するには、次の 2 つの方法があります。

  1. 関数をバインドして状態を定義します。bind(f, _1, state)

    double g(double x, double state) { return x+state; 関数 f = bind(g,_1,state);

  2. ()演算子とクラスを使用します。

struct f { 
  double state; 
  f(double state_):state(state_) {} 
  double operator()(double x) {return x+state;}
};

-method の方が高速に記述できることがわかりましたが、ほとんどの場合、文学ではファンクターをクラスの演算子bindと見なしているため、隠れた石があるかどうか疑問に思っています。()

4

3 に答える 3

3

3. 方法はラムダ式です。

auto f = [state]( double x ) { return x * state; };
于 2013-08-11T10:36:31.803 に答える
0

structそれを行うためのより速い方法のように見えます:

11:01:56 ~/try 
> g++ -std=c++11 main.cpp ; ./a.out
in 2265 ms, functor as a struct result = 1.5708e+16
in 31855 ms, functor through bind result = 1.5708e+16
11:02:33 ~/try 
> clang++ -std=c++11 main.cpp ; ./a.out
in 3484 ms, functor as a struct result = 1.5708e+16
in 21081 ms, functor through bind result = 1.5708e+16

コード:

#include <iostream>
#include <functional>
#include <chrono>

using namespace std;
using namespace std::placeholders;
using namespace std::chrono;

struct fs {
  double s;
  fs(double state) : s(state) {}
  double operator()(double x) {
    return x*s;
  }
};

double fb(double x, double state) {
  return x*state;
}

int main(int argc, char const *argv[]) {
  double state=3.1415926;

  const auto stp1 = system_clock::now();
  fs fstruct(state);
  double sresult;
  for(double x=0.0; x< 1.0e8; ++x) {
    sresult += fstruct(x);
  }
  const auto stp2 = high_resolution_clock::now();
  const auto sd = duration_cast<milliseconds>(stp2 - stp1);  
  cout << "in " << sd.count() << " ms, "; 
  cout << "functor as a struct result = " << sresult << endl;

  const auto btp1 = system_clock::now();
  auto fbind = bind(fb, _1, state);
  double bresult;
  for(double x=0.0; x< 1.0e8; ++x) {
    bresult += fbind(x);
  }
  const auto btp2 = high_resolution_clock::now();
  const auto bd = duration_cast<milliseconds>(btp2 - btp1);  
  cout << "in " << bd.count() << " ms, "; 
  cout << "functor through bind result = " << bresult << endl;

  return 0;
}

アップデート (1)

関数オブジェクトとして関数を持つこともできます:

struct fbs {
  double operator()(double x, double state) const {
    return x*state;
  }
};

そしてmain.cppで:

  const auto bstp1 = system_clock::now();
  auto fbindstruct = bind(fbs(), _1, state);
  double bsresult;
  for(double x=0.0; x< 1.0e8; ++x) {
    bsresult += fbindstruct(x);
  }
  const auto bstp2 = high_resolution_clock::now();
  const auto bsd = duration_cast<milliseconds>(bstp2 - bstp1);  
  cout << "in " << bsd.count() << " ms, "; 
  cout << "functor through bind-struct result = " << bsresult << endl;

速度を変更しませんでした:

> g++ -std=c++11 main.cpp ; ./a.out
hi
in 2178 ms, functor as a struct result = 1.5708e+16
in 31972 ms, functor through bind result = 1.5708e+16
in 32083 ms, functor through bind-struct result = 1.5708e+16
12:15:27 ~/try 
> clang++ -std=c++11 main.cpp ; ./a.out
hi
in 3758 ms, functor as a struct result = 1.5708e+16
in 23503 ms, functor through bind result = 1.5708e+16
in 23508 ms, functor through bind-struct result = 1.5708e+16

更新 (2)

最適化を追加すると、同様の時間で結果が得られます。

> g++ -std=c++11 -O2 main.cpp ; ./a.out
hi
in 536 ms, functor as a struct result = 1.5708e+16
in 510 ms, functor through bind result = 1.5708e+16
in 472 ms, functor through bind-struct result = 1.5708e+16
12:31:33 ~/try 
> clang++ -std=c++11 -O2 main.cpp ; ./a.out
hi
in 388 ms, functor as a struct result = 1.5708e+16
in 419 ms, functor through bind result = 1.5708e+16
in 456 ms, functor through bind-struct result = 3.14159e+16

GCC 4.8.1 および Clang 3.3

Clang 3.3 では、「bind-struct」の場合に間違った結果が返されることに注意してください。

アップデート(3)

Is there a macro-based adapter to make a functor from a class?でさらにパフォーマンス テストがあります。

于 2013-08-11T18:06:35.590 に答える