explicit可以提公升構造物件效率

2021-10-06 15:17:16 字數 1636 閱讀 4098

隱式轉換有點像是「預處理」,以函式呼叫為例,函式呼叫的引數是嚴格的匹配的,假設函式接受乙個double引數,在呼叫之時若傳入了乙個int,隱式轉換,將乙個不匹配的引數「預處理」成符合的引數,在本例,隱式轉換就將int轉換成double,對於乙個強語言來說,這將產生乙個錯誤[1]。就這個層面上來講,c++作為乙個弱語言,定義隱式轉換規則有利於:

對於基本資料型別,c++定義了保證精度的轉換規則;對於stl標準庫中的容器,定義了必要的轉換規則,這些規則往往就是非explicit建構函式。

3.1 隱式轉換過程

當使用者在自定義乙個類時,如果建構函式的引數實際作用只有乙個[3],使用該類作為引數的函式,將會啟用類的隱式轉換規則:那麼編譯器將會在沒有被宣告為explicit關鍵字建構函式尋找匹配的建構函式,將不符合的引數「預處理」(構造)成乙個臨時物件,繼續進行函式的匹配。如果我們不想要這個建構函式成為隱式轉換的規則,那麼將其宣告為explicit即可,看上去explicit的宣告將規則隱藏了。

特別地,拷貝建構函式也是乙個函式,在使用拷貝構造時,引數也可以發生隱式轉換。

class aa(

const a&a)

}

就好像這樣是用int進行拷貝構造一樣。

a a=1;
在這裡a a=1;拷貝構造輸入的引數是乙個int,不是拷貝構造期望的類物件,編譯器將會嘗試構造乙個臨時物件以完成拷貝過程,於是編譯器就拿著這個引數int比對現有的建構函式,完成臨時物件的構造,構造完成後重新傳入拷貝建構函式。這樣一來就完成了拷貝構造的隱式轉換。這裡(非拷貝、單引數)建構函式實際上就是定義了類的乙個轉換規則。

3.2 explicit宣告建構函式提高效率

如果我們不想讓部分建構函式成為轉換規則,只需要在宣告最前邊加上explicit即可。

一般而言,構造乙個物件由兩類方法,一是直接構造,二是拷貝構造。拷貝構造接收自身類型別,意味著可以利用直接構造來完成隱式轉換,從而完成拷貝構造,看上去我們拷貝構造能完成與直接構造相同的功能。

但是,拷貝構造替代直接構造有乙個缺陷,那就是效率較低。有時候使用拷貝隱式構造是沒有必要的,因為你既然要初始化乙個物件,為什麼還要構造乙個臨時物件再進行拷貝構造(多了一次拷貝構造),這就是為什麼編譯器要將隱式拷貝構造優化成直接構造的原因[4]。通過將建構函式宣告為explicit,就是希望你通過直接構造而不是拷貝構造方式來完成構造(構造後->拷貝構造),這可能是一種效能優化的方式。注意到智慧型指標shared_ptr將引數為普通指標建構函式設定為explicit,這就意味著,如果你如果想通過指標型別來初始化乙個shared_ptr只能通過直接構造的方式來完成,或許就是為了減少一次拷貝構造吧?

[1] 《什麼是弱型別語言、強型別語言?》

[2] 《c語言入坑指南-整型的隱式轉換與溢位》

[3] 如果建構函式只有乙個引數沒有預設值也算是乙個實際引數

[4] 編譯器可以但不是必須這麼做,依賴具體實現

explicit建構函式

按照預設規定,只有乙個引數的建構函式也定義了乙個隱式轉換,將該建構函式對應資料型別的資料轉換為該類物件,如下面所示 class string string s1 hello ok 隱式轉換,等價於string s1 string hello 但是有的時候可能會不需要這種隱式轉換,如下 class s...

explicit建構函式

在閱讀slicer原始碼時,遇見explicit修飾的建構函式,比較迷惑 explicit qslicerigsreadermodule qobject parent 0 下面就解釋這個問題。按照預設規定,只有乙個引數的建構函式也定義了乙個隱式轉換,將該建構函式對應資料型別的資料轉換為該類物件,如下...

Qt C 建構函式與explicit

1 預設建構函式 預設建構函式是指所有引數都提供了預設值的建構函式,通常指無參的建構函式或提供預設值的建構函式。如類test1和test2的建構函式 class test1 default constructor 或 class test2 default constructor 如果你沒有為你的類...