c++11的std::function是一大亮點,具體優點我就不一一細說了,今天我來說一些使用std::function帶來的常見問題及處理。
std::function<bool(int,int)> compare = [](int a, int b){
return a > b;
};
compare(1, 2);
以上是正常的基本使用。
但如果std::fucntion是類成員的時候,有時候在就會莫名其妙的crash了。
如下:
class Test
{
public:
std::function<void()> delegate;
void testDelegate()
{
if (delegate) {
delegate();
}
}
};
void main()
{
Test t;
t.delegate = [](){
printf("t.delegate\n");
};
t.testDelegate();
Test * m = new Test;
string s = "hello world!";
m->delegate = [m, s](){
delete m;
printf("m->delegate\n%s\n", s.c_str());
};
m->testDelegate();
}
第一個測試是正常的使用,第二個測試就可能會crash了。爲什麼呢,因爲m已經被釋放了,成員delegate也被析構了。
執行delete m後,函數實體已經消亡,包括[]中catch的所有變量都也析構了,如變量s。所以再操作相關對象時就會crash,如果沒有crash那隻能說你運氣好。
也許你會問誰這麼笨直接寫delete在裏面,反正我是遇到了,不管是不是直接delete的。
解決方法也很簡單,但有點煩索。
class Test
{
public:
std::fucntion<void()> delegate;
void testDelegate()
{
if (delegate) {
auto copy = delegate; // 複製函數實例,copy將不受Test對象的析構影響
copy();
}
}
};
解決!
第二個問題,是std::function和初始化列表std::initializer_list結合使用引起的。
struct Test
{
int m;
string str;
std::function<void()> callback;
};
void main()
{
Test t1 = {0, "", [](){}};
Test t2 = {0, "", nullptr};
Test t3 = {0, ""};
Test t4 = {0};
}
這時候t3和t4的callback,可能不會正常初始化爲nullptr。現象是隨機crash,猜測可能是篡改了其它的內存。
t1和t2不知道會不會正常,現在如果struct裏面有function,我會以次賦值,不再使用initializer_list,所以不是很清楚,有興趣的同學可以自己嘗試。
解決方法,就是隻能避免這種用法。
~~~~~~~~~~~~~~~~~~~
以上是我的個人遇到的問題及解決,僅供參考,不喜勿噴!