Object-C++關于回調的那些事

在我們學習編寫程序當中 回調 是我們最常見的詞語之一蟹略,回調 事件大大的增強了我們程序的邏輯性和可讀性登失,是編程中不可缺少的魁寶。當然挖炬,我們怎么說也是學過 Object-C的人揽浙,再怎么說我們也知道在 OC 當中回調事件有代理,block 這兩種慣用的模式意敛,但是馅巷,在 C/C++ 中,我們又如何使用回調呢草姻?使用回調又如何確保安全(當然指線程安全和防止內存泄露呢)钓猬?今天博主就帶大家好好認識一番。

博主先拋磚引玉撩独,寫出兩種 C/C++ 常用的回調手段敞曹,函數(shù)指針lambda 表達式

1综膀、使用函數(shù)指針

首先我們先理解一下什么函數(shù)指針:函數(shù)指針澳迫,看名字也就知道嘛,就是指向函數(shù)的指針咯剧劝,貌似好像是廢話橄登,額,我們就實操講解一下吧。

void function_a() {
printf("大家好拢锹,我就是一個函數(shù)");
};

// 調用
void (*f_p)() = NULL; // 一個函數(shù)指針
f_p = &function_a;
f_p();

運行上面代碼谣妻,得到的 logger 為 :大家好,我就是一個函數(shù)

分析
上面代碼中面褐,我們首先定義了一個函數(shù) void function_a() 拌禾,之后我們就能看到所謂的函數(shù)指針定義了 void (*f_p)(),很明顯,它指向了函數(shù) function_a 的地址展哭,之后我們便能通過函數(shù)指針來直接使用函數(shù)了湃窍。

實戰(zhàn)
那么我們該如何使用函數(shù)指針實現(xiàn)我們的回調呢?我們模仿工程當中使用匪傍,來為大家解決疑惑

Class CBClass {
public:
std:string m_str; 
void (*m_callback)();
}

void fun_callback(CBClass *cb){
cb->m_str = "we reset m_str";
}

// 調用
CBClass *cb_ = new CBClass();
cb->m_callback = &fun_callback;
cb->m_callback(cb);
std::cout << cb->m_str << std::endl;

運行上面程序您市,得到的 loggler 為: we reset m_str

這就是我們在用 C++ 面向對象的時候使用的回調,個人感覺役衡,還是跟代理有點想得茵休,因為你還可以設置一個 auto 的代理變量,然后直接通過函數(shù)指針調用其方法手蝎,具體怎么設計這里就不做過多的描述了榕莺,留給小伙伴們一個實踐的命題吧。

2棵介、使用 lambda 表達式

很顯然钉鸯, lambda 表達式 是 C++ 11 出來的產(chǎn)物,一部分年老的程序員還是對其抱著觀望的態(tài)度邮辽,不敢貿然使用唠雕,但是,你覺我們像是年老的程序員嘛 0 0吨述,不岩睁,我們是代碼的搬運工。好吧揣云,我們來理解什么是 lambda 表達式

auto lambda_ = [=]() {
cout << "大家好我是一個 lambda 表達式"
};

auto lambda_ = [&]() {
cout << "大家好我又是一個 lambda 表達式"
};

上面代碼中使用了兩種 lambda 表達式捕儒,學過 Swift 的小伙伴們都知道啥是 值類型引用類型,我們同時可以理解為 [=] 相當于 值類型 邓夕, 而 [&] 相當于引用類型肋层。當然,也有 Object-C 的理解方法翎迁,[=] 相對與在你使用 block 中單單只是使用外部變量的值,并不關心使用變量的改變净薛,具有使用如下

int a = 10;
void (^Callback)() = ^() {
NSLog(@"%d", a);
};

但是汪榔,如果你想要不管是 lambda內部或外部修改引用變量的值時,就要使用到 [&] ,相當于 Object-C中的 __block使用了痴腌,如下

__block int a = 10;
void (^Callback)() = ^() {
NSLog(@"%d", a);
};
a = 20;

好了雌团,lambda表達式這么像我們的 Object-C的 block,相信大家都異常的歡喜了士聪,但是我們在實戰(zhàn)當中如何使用 lambda 呢锦援?

Class CBClass {

using Callback = function<void()>;

public:
std:string m_str; 
Callback m_callback;
}

// 調用
CBClass *cb_ = new CBClass();
cb_->m_callback = [=](){
cb_->m_str = "we reset m_str";
};
cb_->m_callback();
cout << cb_->m_str << endl;
delete cb_;

運行以上代碼,得到的 logger 為 : we reset m_str

大家看出剥悟,lambda 的調用方式真的是跟 block像得不能再像了灵寺。

但是是什么讓老一輩的 C++ 對這種新語法往而卻步呢? 難道 lambda 會坑得他們變成寶字輩区岗?
沒錯略板,lambda 也有坑。已上面 CBClass 為列子觀看以下代碼慈缔。

shared_ptr<CBClass> bc_ = make_shared<CBClass>();
cb_->m_callback = [=](){
cb_->m_str = "we reset m_str";
};
cb_->m_callback();
cout << cb_->m_str << endl;

上面代碼中叮称,我們使用了共享指針 shared_ptr 來讓 CBClass使用自動引用計數(shù)器,將內存交給系統(tǒng)管理藐鹤,這段運行并不會崩潰瓤檐,也不會報錯,唯一的致命點在于內存泄露娱节,用慣了 Object-C ARC的我們看得出挠蛉,這泥馬存在這循環(huán)引用呀。
我們先看看為什么會發(fā)生循環(huán)引用

發(fā)生循環(huán)引用

沒錯括堤,就是這么坑爹碌秸,未使用過 C++11 特性的舊程序員們,又怎么料到這種事情呢悄窃,然后內存過多地方如此的寫讥电,程序崩潰0 0。
為了解決上面的循環(huán)引用轧抗,我們當然要將對象實現(xiàn)弱引用恩敌,讓不讓 lambda 來為我們的 cb_對象管理內存咯。

shared_ptr<CBClass> bc_ = make_shared<CBClass>();
auto weak_cb = cb_->get();
cb_->m_callback = [=](){
weak_cb->m_str = "we reset m_str";
};
cb_->m_callback();
cout << cb_->m_str << endl;

上面代碼横媚,相當于如下效果

弱引用

但是為什么上面沒有使用 shared_ptr 的時候沒有發(fā)生循環(huán)引用呢纠炮?大哥,我們已經(jīng)手動 delete 了 cb_灯蝴。


至此恢口,博主拋磚引用的實現(xiàn)了兩種 C/C++ 中的回調方法,接下來小伙伴們發(fā)揮自己的想象力穷躁,實現(xiàn)更的方式吧耕肩。

大哥,既然來了,就點個喜歡吧猿诸。

心如止水婚被,奮力前行

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市梳虽,隨后出現(xiàn)的幾起案子址芯,更是在濱河造成了極大的恐慌,老刑警劉巖窜觉,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谷炸,死亡現(xiàn)場離奇詭異,居然都是意外死亡竖螃,警方通過查閱死者的電腦和手機淑廊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來特咆,“玉大人季惩,你說我怎么就攤上這事∧甯瘢” “怎么了画拾?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長菜职。 經(jīng)常有香客問我青抛,道長,這世上最難降的妖魔是什么酬核? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任蜜另,我火速辦了婚禮,結果婚禮上嫡意,老公的妹妹穿的比我還像新娘举瑰。我一直安慰自己,他們只是感情好蔬螟,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布此迅。 她就那樣靜靜地躺著,像睡著了一般旧巾。 火紅的嫁衣襯著肌膚如雪耸序。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天鲁猩,我揣著相機與錄音坎怪,去河邊找鬼。 笑死廓握,一個胖子當著我的面吹牛芋忿,可吹牛的內容都是我干的炸客。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼戈钢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了是尔?” 一聲冷哼從身側響起殉了,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拟枚,沒想到半個月后薪铜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡恩溅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年隔箍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脚乡。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜒滩,死狀恐怖,靈堂內的尸體忽然破棺而出奶稠,到底是詐尸還是另有隱情俯艰,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布锌订,位于F島的核電站竹握,受9級特大地震影響,放射性物質發(fā)生泄漏辆飘。R本人自食惡果不足惜啦辐,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜈项。 院中可真熱鬧芹关,春花似錦、人聲如沸战得。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽常侦。三九已至浇冰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間聋亡,已是汗流浹背肘习。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坡倔,地道東北人漂佩。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓脖含,卻偏偏與公主長得像,于是被迫代替她去往敵國和親投蝉。 傳聞我的和親對象是個殘疾皇子养葵,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內容