noexcept
是C++11引入的,表明函數(shù)是否會(huì)拋出異常。正確使用它可以優(yōu)化性能,錯(cuò)誤使用則會(huì)帶來(lái)麻煩。
noexcept
使用語(yǔ)法有兩種:
第二種使用方式允許用表達(dá)式?jīng)Q定是否noexcept
起效果,當(dāng)expression
的值為true的時(shí)候起效果,否則不起效。expression
是編譯時(shí)求值,一切都是在編譯時(shí)決定。
如果一個(gè)函數(shù)標(biāo)注成noexcept
,
如果noexcept的函數(shù)執(zhí)行時(shí)出了異常,包括所調(diào)用的函數(shù)拋出的異常,程序會(huì)馬上terminate,即使套上try...catch
也仍舊會(huì)terminate。并且編譯器不會(huì)幫你檢查這樣的風(fēng)險(xiǎn)。
在需要決定是調(diào)用移動(dòng)構(gòu)造函數(shù)(或者移動(dòng)賦值運(yùn)算符)還是復(fù)制構(gòu)造函數(shù)(或者復(fù)制賦值運(yùn)算符)時(shí),noexcept
會(huì)影響決定。因?yàn)橐苿?dòng)語(yǔ)法會(huì)“破壞”原來(lái)的源對(duì)象的內(nèi)容,造成無(wú)法在出現(xiàn)異常情況下恢復(fù)狀態(tài)。因此只有移動(dòng)構(gòu)造函數(shù)(或者移動(dòng)賦值運(yùn)算符)標(biāo)明為noexcept
時(shí),才能在這種情況下使用移動(dòng)構(gòu)造函數(shù)(或者移動(dòng)賦值運(yùn)算符)替代復(fù)制構(gòu)造函數(shù)(或者復(fù)制賦值運(yùn)算符)。
一個(gè)例子就是STL庫(kù)中的vector
的擴(kuò)容,擴(kuò)容涉及到是復(fù)制對(duì)象還是移動(dòng)對(duì)象的問(wèn)題,就是上述的問(wèn)題。當(dāng)對(duì)象的移動(dòng)構(gòu)造函數(shù)可能會(huì)拋出異常的時(shí)候,vector
是”不敢“在這個(gè)場(chǎng)景下調(diào)用的,因?yàn)槌隽水惓o(wú)法原恢復(fù)狀態(tài)。
詳細(xì)邏輯如下:
以下是測(cè)驗(yàn)代碼:
class A {
public:
A() { std::cout<< "constructor"<< std::endl; }
A(const A& a) { std::cout<< "copy constructor"<< std::endl; }
A(const A&& a) noexcept { std::cout<< "move constructor"<< std::endl; } // 有noconcept時(shí),擴(kuò)容時(shí)用移動(dòng)構(gòu)造
// A(const A&& a) { std::cout<< "move constructor"<< std::endl; } // 去掉noconcept時(shí),擴(kuò)容時(shí)用拷貝構(gòu)造
};
int main() {
std::vector v;
v.reserve(1);
for (int i = 0; i< 10; i++) {
A a; // 構(gòu)造一個(gè)A類的實(shí)例。
v.push_back(a); // 添加進(jìn)容器時(shí)會(huì)調(diào)用一次復(fù)制構(gòu)造,如果容量不夠則會(huì)擴(kuò)容,這時(shí)候會(huì)選擇復(fù)制構(gòu)造還是移動(dòng)構(gòu)造。
}
return 0;
}
不適用場(chǎng)景其他情況均不太適合使用。因?yàn)椋?/p>
noexcept
之后就可能很難移除,因?yàn)槠渌a可能會(huì)直接或間接引用到它,且假設(shè)不會(huì)有異常;noexcept
的函數(shù)自己或者調(diào)用的函數(shù)(直接或間接)拋出異常,直接終止,非常簡(jiǎn)單粗暴。因此出了幾個(gè)有限的適用場(chǎng)景外,其他情況下不要用noexcept
。
以下圖表是來(lái)自于 C++ noexcept and move constructors effect on performance in STL Containers — TRYING TO FIND THE OBVIOUS (hlsl.co.uk) 這篇博客的實(shí)驗(yàn)結(jié)果。
根據(jù)實(shí)驗(yàn)結(jié)果,性能提升了兩倍!
雖然noexcept
會(huì)在某些情況下提升性能,但是由于它的危險(xiǎn)性,包括發(fā)生異常直接終止程序且編譯器不會(huì)幫你檢查,除了以下情況下都不建議使用。
1、2 已經(jīng)在前面說(shuō)過(guò)了,不再贅述。對(duì)于3、4,析構(gòu)函數(shù)本身不應(yīng)該拋異常,簡(jiǎn)單函數(shù)一般不會(huì)發(fā)生異常,因此可以放心標(biāo)注noexcept
。
c++ 從vector擴(kuò)容看noexcept應(yīng)用場(chǎng)景 - 知乎 (zhihu.com)
C++ noexcept and move constructors effect on performance in STL Containers — TRYING TO FIND THE OBVIOUS (hlsl.co.uk)
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧