ラムダ式は、オーバーロードされた関数呼び出し演算子を含むクラスを作成し、変数をメンバーとして参照することによって実装されます。これは、ラムダ式のサイズが参照される変数の数に応じて変化することを示唆しています。ただし、std::function は固定サイズである必要があります。 std::function の実装を理解することは非常に重要です。
可変サイズのファンクターの型消去
std::function は、型消去と呼ばれる手法を使用して、次のファンクターを処理します。可変サイズ。 int(double):
struct callable_base { virtual int operator()(double d) = 0; virtual ~callable_base() {} }; template <typename F> struct callable : callable_base { F functor; callable(F functor) : functor(functor) {} virtual int operator()(double d) { return functor(d); } }; class function_int_double { std::unique_ptr<callable_base> c; public: template <typename F> function(F f) { c.reset(new callable<F>(f)); } int operator()(double d) { return c(d); } };
への関数ポインターをラップする std::function の簡略化された例を考えてみましょう。この例では、std::function は unique_ptr を多態的な callable_base 型に格納します。さまざまなファンクターに対して、callable_base から派生した新しい型が作成され、動的にインスタンス化されます。 std::function オブジェクトは、ヒープ内のさまざまなサイズのファンクターに対応しながら、一貫したサイズを維持します。
動的ディスパッチと最適化
パフォーマンスを向上させるために、実際の実装ではstd::function の動的なディスパッチを最適化し、小さなオブジェクトの最適化を活用します。ただし、基本的な概念は変わりません。
std::function のコピーの動作
std::function のコピーには、カプセル化された呼び出し可能オブジェクトのコピーが伴います。 。これは、次のテストで確認されます。
int main() { int value = 5; typedef std::function<void()> fun; fun f1 = [=]() mutable { std::cout << value++ << '\n' }; fun f2 = f1; f1(); fun f3 = f1; f2(); f3(); }
出力 демонстрирует (5, 5, 6) は、状態を共有するのではなく、関数オブジェクトのコピーが作成されることを示します。
std::function の実装を理解することで、さまざまなサイズのファンクターを効率的に使用できるようになります。
以上が`std::function` は可変サイズのファンクターをどのように処理しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。