如何實現std::function:類型擦除和堆分配
std::function 的一個關鍵實現細節是它的能力包裝任何可調用對象,包括lambda 表達式。雖然 lambda 的大小不同,但 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); } };
這裡,std::function 成立一個 unique_ptr 到一個基本的 callable_base 類型。對於所使用的每個唯一函子,派生類型可呼叫
std::function 的副本會觸發內部可呼叫物件的副本,而不是共享狀態。從可變捕獲變數的值遞增的測試中可以明顯看出這一點:
int value = 5; std::function<void()> f1 = [=]() mutable { std::cout << value++ << '\n'; }; std::function<void()> f2 = f1; // Prints 5 f1(); // Prints 5 (copy of mutable state) f2();
因此,std::function 使用類型擦除和堆分配有效地包裝不同大小的可調用物件。堆分配用於根據包裝的可呼叫實例化動態類型,確保 std::function 本身的固定大小。
以上是儘管包裝了不同大小的可呼叫對象,但「std::function」如何實現固定大小?的詳細內容。更多資訊請關注PHP中文網其他相關文章!