2015-11-04 80 views
3

我寫了一個對象,存儲一個std::function<void(void*)>,它作爲參數傳遞給構造函數。該對象稍後將在稍後的某個時刻回調該std ::函數。這是實施和工作很好。減少std :: bind模板代碼膨脹?

在使用該對象的每個類,它們調用初始化列表構造像這樣:

mCallbackObj(std::bind(&MyClass::MyFunc, this, _1)) 

然而,我發現,每一個包含該對象作爲成員類增加我的代碼空間大約2K。由於可能有數百個使用該對象的地方,以及有限的代碼空間選項(這是一個嵌入式產品),因此每次使用2k次命中是不可接受的。

一個有趣的觀察是,如果一個類具有第二對象:

mCallbackObj2(std::bind(&MyClass::MyOtherFunc, this, _1)) 

這僅通過一些〜150字節增加碼域 - 非常可接受!只有當對象用於不同的類時,我纔看到2K命中。把所有的類放在一個.cpp文件中並沒有幫助 - 每個包含這個對象的類仍然有2k命中。

我玩過extern template class std::function<void(void*)>;,但這對ROM尺寸沒有影響。

我使用的是gcc 4.8。我很樂意使用std::functionstd::bind,但我們即將放棄並切換到類方法指針。它們幾乎沒有那麼幹淨,但希望ROM的效率更高。

在放棄之前,有沒有其他選擇可以幫助減少我的模板碼空間膨脹?

+1

我想知道如果你使用'[this](void * p){return this-> MyFunc(p); }'代替'bind'。 –

+0

@IgorTandetnik可能稍微好一點,但是'std :: function'本身仍然會產生大量的樣板文件。 –

+1

std :: function可能是膨脹的原因。 (https://www.youtube.com/watch?v=zt7ThwVfap0)您可以嘗試用lambda替換綁定,但這不會減少二進制大小。 – John

回答

1

我挖掘了一下,看了@John的視頻std::function。在video中,STL建議使用超過std::bind的lambda,原因有幾個。

我試着將代碼轉換爲使用Lambda,這正是上面推薦的@Igor Tandetnik。它明顯更好。

mCallbackObj(std::bind(&MyClass::MyFunc, this, _1)) 

需要額外的2,888字節的代碼空間。相反使用

mCallbackObj([this](void *info){MyFunc(info);}) 

只需要額外的812字節!這顯然更好,而且足夠我的用例。對於不熟悉std :: bind語法的C++程序員來說,lambda解決方案也更易於閱讀。


更新 -

撞擊到GCC 6.0和調整我們的編譯器標誌(我們並不總是在傳遞之前-02)後,我重新測試這一點。

Lambda:   216 bytes 
std::bind:   221 bytes 
function pointer: 228 bytes 

所有3現在更合理。我們主要使用lambdas,因爲一旦開發人員熟悉語法,它們是最容易閱讀的。