功能開銷
std::function
會導致很大的開銷。因為 std::function
具有[value semantics] [1],所以它必須將給定的 callable 複製或移動到自身中。但由於它可以採用任意型別的 callable,因此它經常需要動態分配記憶體來執行此操作。
一些 function
實現具有所謂的小物件優化,其中小型別(如函式指標,成員指標或具有極少狀態的函子)將直接儲存在 function
物件中。但即便如此,只有在型別為 noexcept
移動構造時才有效。此外,C++標準並不要求所有實現都提供一個。
考慮以下:
//Header file
using MyPredicate = std::function<bool(const MyValue &, const MyValue &)>;
void SortMyContainer(MyContainer &C, const MyPredicate &pred);
//Source file
void SortMyContainer(MyContainer &C, const MyPredicate &pred)
{
std::sort(C.begin(), C.end(), pred);
}
模板引數將是 SortMyContainer
的首選解決方案,但我們假設無論出於何種原因這都是不可能或不可取的。SortMyContainer
不需要將 pred
儲存在自己的呼叫之外。然而,如果賦予它的仿函式具有一些非平凡的大小,pred
可能會很好地分配記憶體。
function
分配記憶體,因為它需要複製/移動的東西; function
獲得它所給予的可呼叫權。但是 SortMyContainer
不需要擁有可呼叫的東西; 它只是引用它。所以在這裡使用 function
是過度的; 它可能是有效的,但它可能不是。
沒有標準庫函式型別僅引用可呼叫函式。因此,必須找到替代解決方案,或者你可以選擇承擔開銷。
此外,function
沒有有效的方法來控制物件的記憶體分配來自何處。是的,有采取 allocator
建構函式,但[許多實現不正確地實現他們…甚至根本 ] [2]。
Version >= C++ 17
採取 allocator
的 function
建構函式不再是型別的一部分。因此,無法管理分配。
呼叫 function
也比直接呼叫內容慢。由於任何 function
例項都可以保持任何可呼叫,因此通過 function
的呼叫必須是間接的。呼叫 function
的開銷是虛擬函式呼叫的順序。