std::function 的作用很強大,他讓vector等儲存不同型別函式的物件: function, functor, lambda…成為了可能。但他有乙個潛在的效能風險:在儲存lambda/bind時,如果物件的大小 大於兩個指標的大小,他就需要分配動態空間。這是大部分人寫c++的人不期望看到的。
先看function實現的幾段**:6.1.0a-2/include/c++/6.1.0/functional
void* _m_access()
const void* _m_access() const
template_tp&
_m_access()
1651 _m_init_functor(_any_data& __functor, _functor&& __f, true_type)
1652
1653
1654 static void
1655 _m_init_functor(_any_data& __functor, _functor&& __f, false_type)
1656
1625 static void
1626 _m_init_functor(_any_data& __functor, _functor&& __f)
1627
呼叫哪個函式由_local_storage決定.
1538 class _function_base
1539 ;
咋一看,這個union的大小應該是乙個指標的大小,裡面有個關鍵成員:void (_undefined_class:?_m_member_pointer)(); 指向成員函式的指標,指向成員函式的指標的大小是2個指標的大小。所以結果就是:如果傳入functor的大小大於兩個指標的大小,就會分配動態記憶體。函式指標的大小就是乙個指標的大小,那什麼時候functor會大於乙個指標的大小:lambda和bind。我們以lambda為例來看。bind和lambda的效果一樣。
編譯器在碰到lambda函式時,事實上,會生成乙個物件來儲存lambda函式。這個物件過載了operator(),所以能像函式一樣呼叫。同時,這個物件還有資料成員,這些資料成員就是捕獲來的物件。譬如:
auto lf = [&a, &b];
std::cout << sizeof(lf) << std::endl;
``這個物件捕獲了兩個引用(相當於兩個指標的大小),所以輸出就是16.
# 類成員函式的指標的大小
前面提到類成員函式的指標大小是兩個指標的大小。為什麼? 因為類成員函式的指標還有乙個偏移量, 這個類相對於基類指標的偏移 。
考慮三個類:
```c++
#include #include class a
private:
int a;
};class b
private:
int a;
};class derived: public a, public b ;
我們用derived的物件去訪問函式geta期望返回的是class a的a, 如果訪問getb期望返回的是class b的a;
derived d;
std::cout << "geta: " << d.geta() << ", getb: " << d.getb() << std::endl;
輸出是:
b address: 0x7ffe00762494
a address: 0x7ffe00762490
geta: 1, getb: 2
訪問b的時候,this指標做了偏移,指向了class b在class d中的開始位址。假如使用成員函式指標,這個偏移量,只有在成員函式指標被賦值的時候才能知道。
考慮函式:
void print(derived & d, int (derived::*p_mem)())
print(d, &derived::geta);
print(d, &derived::getb);
的輸出就是:
a address: 0x7ffc8164e770
print --------
object ptr: 0x7ffc8164e770
function ptr: 0x400b82
point adj: 0
value: 1
b address: 0x7ffc8164e774
print --------
object ptr: 0x7ffc8164e770
function ptr: 0x400bc4
point adj: 0x4
value: 2
參考文章:
如果用std::function的變數來儲存lambda或bind的函式物件時,需要格外注意,如果物件的大小大於兩個指標的大小,就會發生動態記憶體分配,影響效能。
jquery mobile AJAX特性的陷阱
簡單情況是 mvc 重定向,url不變 試了n種方式,跳來跳去,無解,服務端跳,寫js跳,生成跳轉中間頁跳。失敗 後來一看,明明已經跳到新頁了,樣式什麼還是原頁的,有點火大了。出去溜一圈,喝杯水,和同事東拉西扯一通。回頭一看,突然反應過來,這不是ajax的效果麼,坑我半個多小時。為加驗證,是手動呼叫...
std function的本質和使用特性
1.仿函式 又叫std function,是c 中的乙個模板類 2.c語言中的函式指標 int add int a,int b typedef int func int,int 給函式型別定義別名 func func1 func1 add 給函式指標初始化 或者int func1 int,int a...
concat 和 group concat的陷阱
group concat mysql中group concat函式能將相同的行組合起來 完整的語法如下 group concat distinct 要連線的字段 order by asc desc 排序字段 separator 分隔符 使用示例 select from aa id name 1 10...