首頁 >後端開發 >C++ >儘管包裝了不同大小的可呼叫對象,但「std::function」如何實現固定大小?

儘管包裝了不同大小的可呼叫對象,但「std::function」如何實現固定大小?

DDD
DDD原創
2024-12-02 06:01:10723瀏覽

How Does `std::function` Achieve Fixed Size Despite Wrapping Callables of Varying Sizes?

如何實現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 物件保持恆定的大小,同時允許它包裝任何可呼叫物件。

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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn