std::function の実装の探索
ラムダ式の世界では、サイズの概念が流動的になります。基本的には、可変サイズの参照を持つクラスでラップされます。ただし、 std::function は固定サイズを必要とします。これは疑問を引き起こします: これはどのように調和するのでしょうか?
答えはタイプ消去にあります。単純化された実装を想像してみましょう。
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 のサイズは一定のままですが、ヒープ上のファンクターの範囲に対応します。
最適化手法では、小さなオブジェクトの最適化を使用したり、間接化を回避したりして、このスキームをさらに洗練させています。ただし、概念的には、中心的な考え方は同じままです。
std::function のコピーに関しては、実験的証拠により、呼び出し可能オブジェクトの独立したコピーが示唆されています。不自然な例:
int main() { int value = 5; typedef std::function<void()> fun; fun f1 = [=]() mutable { std::cout << value++ << '\n' }; fun f2 = f1; f1(); // prints 5 fun f3 = f1; f2(); // prints 5 f3(); // prints 6 (copy after first increment) }
異なる呼び出しによって値が個別に増加するため、出力は共有状態ではなく分離されたコピーを示します。
以上が可変サイズのラムダ式を処理しているにもかかわらず、std::function はどのようにして固定サイズを維持するのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。