OKR落實(shí)常見(jiàn)問(wèn)題:推行 OKR 需要做哪些準(zhǔn)備
876
2025-04-02
沒(méi)有系統(tǒng)學(xué)過(guò),所以這篇寫的基本都是我接觸過(guò)的,接觸過(guò)多少就整理多少吧。
有些特性也不知道是不是新的,反正都是我新接觸的,用的還挺順手。
語(yǔ)法層面
區(qū)間迭代range for
用過(guò)一次我就很喜歡這個(gè)特性了,寫起來(lái)是方便了不少。
for(int i:vec){ cout<
nullptr
這是一個(gè)空指針類的對(duì)象。
我們以前把指針置空都是:
ptr = NULL;
NULL是一個(gè)宏定義,數(shù)值為0。當(dāng)然不是說(shuō)用NULL有什么問(wèn)題,不過(guò)新的規(guī)范都出來(lái)了,就用新規(guī)也沒(méi)什么不好嘛。
強(qiáng)制類型轉(zhuǎn)換(這個(gè)其實(shí)不是)
static_cast:正常的類型轉(zhuǎn)換,static_cast 不能從表達(dá)式中去除 const 屬性 const_cast:用于且僅用于類型轉(zhuǎn)換掉表達(dá)式的 const 或 volatileness 屬性。 dynamic_cast:用于安全地沿著類的繼承關(guān)系向下進(jìn)行類型轉(zhuǎn)換。 reinterpret_cast:在函數(shù)指針類型之間進(jìn)行轉(zhuǎn)換,這個(gè)轉(zhuǎn)換符不是很受待見(jiàn) 其的轉(zhuǎn)換結(jié)果幾乎都是執(zhí)行期定義。 因此,使用reinterpret_casts 的代碼很難移植。
示例:
int a; double result = static_cast
class father { ... }; class son: public father { ... }; void update(son* psw); son sw; // sw 是一個(gè)非 const 對(duì)象。 const son& csw = sw; // csw 是 sw 的一個(gè)引用,它是一個(gè) const 對(duì)象 update(&csw); // 錯(cuò)誤!不能傳遞一個(gè) const son* 變量給一個(gè)處理 son*類型變量的函數(shù) update(const_cast
father* pw; ... update(dynamic_cast
智能指針
智能指針是存儲(chǔ)指向動(dòng)態(tài)分配(堆)對(duì)象指針的類。除了能夠在適當(dāng)?shù)臅r(shí)間自動(dòng)刪除指向的對(duì)象外,他們的工作機(jī)制很像C++的內(nèi)置指針。
在使用對(duì)象的時(shí)候,使用強(qiáng)智能指針;在引用對(duì)象的時(shí)候,使用弱智能指針。
詳情轉(zhuǎn):C++編程經(jīng)驗(yàn)(9):智能指針 – 裸指針管得了的我要管,裸指針管不了的我更要管!
function函數(shù)對(duì)象、bind綁定器、placeholders占位符
這三個(gè)還是要合在一起講的了。
C++編程經(jīng)驗(yàn)(11):std::function 和 bind綁定器,雖然在這一篇里面專門講過(guò)了,但是感覺(jué)有點(diǎn)抽象,重新捋一下,不然我也不長(zhǎng)記性吶。
using MsgHandler = std::function
MsgHandler 是一個(gè)自定義數(shù)據(jù)類型,函數(shù)指針。
既然是一個(gè)數(shù)據(jù)類型,就可以被塞到容器里面:
unordered_map
函數(shù)指針有什么用,它就有什么用,可以用來(lái)推遲函數(shù)的聲明。
綁定器是干嘛的呢?將參數(shù)綁定到函數(shù)指針上的。
以前的綁定器只能綁定一個(gè)參數(shù),所以我們看到的很多古老的需要函數(shù)指針做傳參的函數(shù)都只有一個(gè)參數(shù)傳遞,但是有了新的綁定器就不一樣了。
_msgHanderMap.insert({LOGIN_TYPE,std::bind(&ChatService::login,this,_1,_2,_3)}); //將三個(gè)參數(shù)綁定到login函數(shù)上,由于是在類內(nèi),所以帶上一個(gè)this。 std::bind(&ChatService::login,this,_1,_2,_3) //這三個(gè)參數(shù)使用占位符事先申明
綁定好了,現(xiàn)在要調(diào)用這個(gè)函數(shù)就需要在調(diào)用的時(shí)候傳參,那被綁定的函數(shù)要如何取參數(shù),這就取決于占位符的聲明了。
std::placeholders決定==函數(shù)占用位置取用輸入?yún)?shù)的第幾個(gè)參數(shù)==。
那么現(xiàn)在一條脈絡(luò)就很清楚了。
要使用函數(shù)指針,使用function進(jìn)行函數(shù)指針模板的聲明與調(diào)用;
實(shí)例化function模板所用的函數(shù)可能有不下于1個(gè)的參數(shù),舊的綁定器已經(jīng)不行了,用新的綁定器來(lái)吧;
而函數(shù)指針需要從調(diào)用函數(shù)指針的函數(shù)那里去獲得傳入?yún)?shù),這個(gè)參數(shù)的位置排序的確定就需要靠占位符來(lái)指定了,或許可以稱之為導(dǎo)航符吧。
lambda表達(dá)式
簡(jiǎn)單來(lái)說(shuō),Lambda函數(shù)也就是一個(gè)函數(shù),它的語(yǔ)法定義如下:
[capture](parameters) mutable ->return-type{statement}
1.[capture]:捕捉列表。捕捉列表總是出現(xiàn)在Lambda函數(shù)的開(kāi)始處。實(shí)際上,[]是Lambda引出符。編譯器根據(jù)該引出符判斷接下來(lái)的代碼是否是Lambda函數(shù)。捕捉列表能夠捕捉上下文中的變量以供Lambda函數(shù)使用;
2.(parameters):參數(shù)列表。與普通函數(shù)的參數(shù)列表一致。如果不需要參數(shù)傳遞,則可以連同括號(hào)“()”一起省略;
3.mutable:mutable修飾符。默認(rèn)情況下,Lambda函數(shù)總是一個(gè)const函數(shù),mutable可以取消其常量性。在使用該修飾符時(shí),參數(shù)列表不可省略(即使參數(shù)為空);
4.->return-type:返回類型。用追蹤返回類型形式聲明函數(shù)的返回類型。我們可以在不需要返回值的時(shí)候也可以連同符號(hào)”->”一起省略。此外,在返回類型明確的情況下,也可以省略該部分,讓編譯器對(duì)返回類型進(jìn)行推導(dǎo);
5.{statement}:函數(shù)體。內(nèi)容與普通函數(shù)一樣,不過(guò)除了可以使用參數(shù)之外,還可以使用所有捕獲的變量。
與普通函數(shù)最大的區(qū)別是,除了可以使用參數(shù)以外,Lambda函數(shù)還可以通過(guò)捕獲列表訪問(wèn)一些上下文中的數(shù)據(jù)。具體地,捕捉列表描述了上下文中哪些數(shù)據(jù)可以被Lambda使用,以及使用方式(以值傳遞的方式或引用傳遞的方式)。語(yǔ)法上,在“[]”包括起來(lái)的是捕捉列表,捕捉列表由多個(gè)捕捉項(xiàng)組成,并以逗號(hào)分隔。捕捉列表有以下幾種形式:
1.[var]表示值傳遞方式捕捉變量var; 2.[=]表示值傳遞方式捕捉所有父作用域的變量(包括this); 3.[&var]表示引用傳遞捕捉變量var; 4.[&]表示引用傳遞方式捕捉所有父作用域的變量(包括this); 5.[this]表示值傳遞方式捕捉當(dāng)前的this指針。 6.[]沒(méi)有任何函數(shù)對(duì)象參數(shù)。 7.&a。將 a 按引用進(jìn)行傳遞。 8.a,&b。將 a 按值傳遞,b 按引用進(jìn)行傳遞。 9.=,&a,&b。除 a 和 b 按引用進(jìn)行傳遞外,其他參數(shù)都按值進(jìn)行傳遞。 10.&,a,b。除 a 和 b 按值進(jìn)行傳遞外,其他參數(shù)都按引用進(jìn)行傳遞。
move
對(duì)于move了解不多。
C++11為了解決這個(gè)問(wèn)題,提供了std::move()方法來(lái)將左值轉(zhuǎn)換為右值,從而方便應(yīng)用移動(dòng)語(yǔ)義。move是將對(duì)象的狀態(tài)或者所有權(quán)從一個(gè)對(duì)象轉(zhuǎn)移到另一個(gè)對(duì)象,只是轉(zhuǎn)義,沒(méi)有內(nèi)存拷貝。
類相關(guān)
explicit類型轉(zhuǎn)換運(yùn)算符
防止類構(gòu)造發(fā)生默認(rèn)類型轉(zhuǎn)換
對(duì)這個(gè)關(guān)鍵字我現(xiàn)在持懷疑態(tài)度了,是我的VS壞了,還是我的眼睛瞎了呢?
下面三個(gè)測(cè)試案例結(jié)果都是一樣的。
#include
=default和=delete
如果實(shí)現(xiàn)了默認(rèn)的構(gòu)造函數(shù),編譯器則不會(huì)自動(dòng)生成默認(rèn)版本;可以通過(guò)使用關(guān)鍵字 default 來(lái)控制默認(rèn)構(gòu)造函數(shù)的生成,顯示的指示編譯器生成該函數(shù)的默認(rèn)版本;
如果不想有某些默認(rèn)生成的函數(shù),就設(shè)置一個(gè) =delete。
如果給類手動(dòng)寫了帶參構(gòu)造,那也是無(wú)法顯式使用無(wú)參構(gòu)造函數(shù)了。
如果沒(méi)有了默認(rèn)構(gòu)造,子類就不能不傳參給父類進(jìn)行構(gòu)造了。
override、final
final關(guān)鍵字的作用是使派生類不可覆蓋它所修飾的虛函數(shù)。
override關(guān)鍵字的作用是使派生類被制定的函數(shù)必須是覆蓋它所修飾的虛函數(shù)。
using
現(xiàn)在不僅僅可以用它來(lái)引用名空間了,不過(guò)現(xiàn)在我也不怎么用這個(gè)來(lái)引用名空間了,都是用域作用符::。
現(xiàn)在用它都是用來(lái)替代以前的typedef了,而且一般是和下面的function函數(shù)對(duì)象結(jié)合在一起使用,最近在整muduo,這些接觸到的會(huì)比較多。
volatile
如上圖所示,所有線程的共享變量都存儲(chǔ)在主內(nèi)存中,每一個(gè)線程都有一個(gè)獨(dú)有的工作內(nèi)存,每個(gè)線程不直接操作在主內(nèi)存中的變量,而是將主內(nèi)存上變量的副本放進(jìn)自己的工作內(nèi)存中,只操作工作內(nèi)存中的數(shù)據(jù)。當(dāng)修改完畢后,再把修改后的結(jié)果放回到主內(nèi)存中。每個(gè)線程都只操作自己工作內(nèi)存中的變量,無(wú)法直接訪問(wèn)對(duì)方工作內(nèi)存中的變量,線程間變量值的傳遞需要通過(guò)主內(nèi)存來(lái)完成。
如果對(duì)變量 i 加上 volatile 關(guān)鍵字修飾的話,它可以保證當(dāng) A 線程對(duì)變量 i 值做了變動(dòng)之后,會(huì)立即刷回到主內(nèi)存中,而其它線程讀取到該變量的值也作廢,強(qiáng)迫重新從主內(nèi)存中讀取該變量的值,這樣在任何時(shí)刻,AB線程總是會(huì)看到變量 i 的同一個(gè)值。
它不是原子操作的。
線程
Thread
std::thread無(wú)疑是一個(gè)重磅福利。
std::thread 在
默認(rèn)構(gòu)造函數(shù) thread() noexcept; 初始化構(gòu)造函數(shù) template
默認(rèn)構(gòu)造函數(shù),創(chuàng)建一個(gè)空的 std::thread 執(zhí)行對(duì)象。
初始化構(gòu)造函數(shù),創(chuàng)建一個(gè) std::thread 對(duì)象,該 std::thread 對(duì)象可被 joinable,新產(chǎn)生的線程會(huì)調(diào)用 fn 函數(shù),該函數(shù)的參數(shù)由 args 給出。
拷貝構(gòu)造函數(shù)(被禁用),意味著 std::thread 對(duì)象不可拷貝構(gòu)造。
Move 構(gòu)造函數(shù),,調(diào)用成功之后 x 不代表任何 std::thread 執(zhí)行對(duì)象。
注意:可被 joinable 的 std::thread 對(duì)象必須在他們銷毀之前被主線程 join 或者將其設(shè)置為 detached.
Move 賦值操作(1),如果當(dāng)前對(duì)象不可 joinable,需要傳遞一個(gè)右值引用(rhs)給 move 賦值操作;如果當(dāng)前對(duì)象可被 joinable,則會(huì)調(diào)用 terminate() 報(bào)錯(cuò)。
拷貝賦值操作(2),被禁用,因此 std::thread 對(duì)象不可拷貝賦值。
get_id: 獲取線程 ID,返回一個(gè)類型為 std::thread::id 的對(duì)象。
joinable: 檢查線程是否可被 join。檢查當(dāng)前的線程對(duì)象是否表示了一個(gè)活動(dòng)的執(zhí)行線程,由默認(rèn)構(gòu)造函數(shù)創(chuàng)建的線程是不能被 join 的。另外,如果某個(gè)線程 已經(jīng)執(zhí)行完任務(wù),但是沒(méi)有被 join 的話,該線程依然會(huì)被認(rèn)為是一個(gè)活動(dòng)的執(zhí)行線程,因此也是可以被 join 的。
detach: Detach 線程。 將當(dāng)前線程對(duì)象所代表的執(zhí)行實(shí)例與該線程對(duì)象分離,使得線程的執(zhí)行可以單獨(dú)進(jìn)行。一旦線程執(zhí)行完畢,它所分配的資源將會(huì)被釋放。
swap: Swap 線程,交換兩個(gè)線程對(duì)象所代表的底層句柄
thread 1 id: 1892 thread 2 id: 2584 after std::swap(t1, t2): thread 1 id: 2584 thread 2 id: 1892 after t1.swap(t2): thread 1 id: 1892 thread 2 id: 2584
yield: 當(dāng)前線程放棄當(dāng)前時(shí)間片,操作系統(tǒng)調(diào)度另一線程繼續(xù)執(zhí)行。
sleep_until: 線程休眠至某個(gè)指定的時(shí)刻(time point),該線程才被重新喚醒。
sleep_for: 線程休眠某個(gè)指定的時(shí)間片(time span),該線程才被重新喚醒,不過(guò)由于線程調(diào)度等原因,實(shí)際休眠時(shí)間可能比 sleep_duration 所表示的時(shí)間片更長(zhǎng)。
縮略muduo庫(kù)(5):Thread、EventThread、EventThreadPool
對(duì)這份線程池我還是有自信的。
鎖種
創(chuàng)建lock_guard對(duì)象時(shí),它將嘗試獲取提供給它的互斥鎖的所有權(quán)。當(dāng)控制流離開(kāi)lock_guard對(duì)象的作用域時(shí),lock_guard析構(gòu)并釋放互斥量。
它的特點(diǎn)如下:
創(chuàng)建即加鎖,作用域結(jié)束自動(dòng)析構(gòu)并解鎖,無(wú)需手工解鎖 不能中途解鎖,必須等作用域結(jié)束才解鎖 不能復(fù)制
簡(jiǎn)單地講,unique_lock 是 lock_guard 的升級(jí)加強(qiáng)版,它具有 lock_guard 的所有功能,同時(shí)又具有其他很多方法,使用起來(lái)更強(qiáng)靈活方便,能夠應(yīng)對(duì)更復(fù)雜的鎖定需要。
特點(diǎn)如下:
創(chuàng)建時(shí)可以不鎖定(通過(guò)指定第二個(gè)參數(shù)為std::defer_lock),而在需要時(shí)再鎖定 可以隨時(shí)加鎖解鎖 作用域規(guī)則同 lock_grard,析構(gòu)時(shí)自動(dòng)釋放鎖 不可復(fù)制,可移動(dòng) 條件變量需要該類型的鎖作為參數(shù)(此時(shí)必須使用unique_lock)
示例:
#include
條件變量。
通知方:
獲取 std::mutex, 通常是 std::lock_guard 修改共享變量(即使共享變量是原子變量,也需要在互斥對(duì)象內(nèi)進(jìn)行修改,以保證正確地將修改發(fā)布到等待線程) 在 condition_variable 上執(zhí)行 notify_one/notify_all 通知條件變量(該操作不需要鎖)
等待方:
獲取相同的 std::mutex, 使用 std::unique_lock 執(zhí)行 wait,wait_for或wait_until(該操作會(huì)自動(dòng)釋放鎖并阻塞) 接收到條件變量通知、超時(shí)或者發(fā)生虛假喚醒時(shí),線程被喚醒,并自動(dòng)獲取鎖。喚醒的線程負(fù)責(zé)檢查共享變量,如果是虛假喚醒,則應(yīng)繼續(xù)等待
std :: condition_variable僅適用于 std::unique_lock
對(duì)于只需要通知一次的情況,如初始化完成、登錄成功等,建議不要使用 condition_variable,使用std::future更好。不過(guò)這個(gè)我還沒(méi)有去了解。
在有些場(chǎng)景里面,是需要對(duì)一些資源進(jìn)行鎖定的。但是有些資源實(shí)在是太小了,鎖定的粒度也太小了,不免顯得上鎖解鎖倒成了繁瑣。
比方說(shuō):
_mlock.lock(); count++; _mlock.unlock();
CAS,是基于硬件層面的無(wú)鎖操作,由CPU來(lái)保證。
#include
容器相關(guān)
unordered_XXX
哈希表。
容器的emplace成員
emplace操作是C++11新特性,新引入的的三個(gè)成員emplace_front、emplace 和 emplace_back。這些操作構(gòu)造而不是拷貝元素到容器中,這些操作分別對(duì)應(yīng)push_front、insert 和push_back,允許我們將元素放在容器頭部、一個(gè)指定的位置和容器尾部。
C++
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。