Lambda 表達式是透過建立一個帶有重載函數呼叫運算子的類別並將變數引用為成員來實現的。這表示 lambda 表達式的大小會根據引用變數的數量而變化。但是,std::function 必須具有固定大小。理解 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 將 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中文網其他相關文章!