探索std::function 的實現
在lambda 表達式的世界中,大小的概念變得流動,因為它們是本質上包裝在具有可變大小參考的類別中。然而,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) }
輸出表示隔離副本而不是共用狀態,因為不同的呼叫獨立地增加值。
以上是儘管處理可變大小的 Lambda 表達式,std::function 如何保持固定大小?的詳細內容。更多資訊請關注PHP中文網其他相關文章!