認識這兩種初始化有助於我們加深對語言的理解,可以更好的優化**~
我們常見的幾種初始化的形式:
string str1 = "first"; //
拷貝初始化,編譯器允許把這句話改寫為string str(「first」)
,但是string
類必須有
public
的拷貝(移動)
建構函式
string str2(10,'a'); //
直接初始化
string str3(str2); //
直接初始化
string str4 = string(10,'b'); //
拷貝初始化
string str5 = str4; //
拷貝初始化
string str6 ("strr"); //
直接初始化
開始不理解的朋友可能認為,呼叫拷貝建構函式就是拷貝初始化,所以可能覺得str3也是拷貝初始化,這樣就錯了~
直接初始化:
使用普通的函式匹配即可完成初始化。也就是說只是直接呼叫類的建構函式或拷貝建構函式就能完成初始化的就是直接初始化,我們的str2和str3分別呼叫建構函式和拷
貝建構函式
拷貝初始化:
將物件拷貝到正在建立的物件當中,如果需要還要進行型別轉換。這裡也就是間接呼叫拷貝建構函式,當然大部分情況呼叫拷貝建構函式,有時也可能呼叫移動建構函式。
根據上面的例子,我們可能覺得,只有等號"="出現時,才會是拷貝初始化。
其實不然,在下面三個情況下也會發生拷貝初始化。
1.將乙個物件作為實參傳遞給乙個非引用型別的實參(引用作為引數的話就可以省略拷貝這一操作,所以有時候可以這樣來優化**)
2.從乙個返回型別為非引用的函式返回乙個物件
3.花括號初始化乙個陣列的元素或乙個聚合類(struct)的成員
區分二者的意義是什麼?
對於內建型別來說,其實意義並不大,因為我們認為內建型別不存在建構函式一說,所以直接初始化也好,用等號初始化也好,複雜度可以認為沒有區別。
而對於類型別的物件,拷貝初始化就相當於先建立乙個物件(執行建構函式)再進行拷貝(執行拷貝建構函式),這樣就相當於多執行了一步,效率自然就畢竟低。其實,對於一般的類來說也還好,也不費多少功夫,但是對於乙個龐大複雜的繼承類,構造乙個物件可能需要向上多次構造基類,成員變數不斷的申請記憶體與初始化,這樣的步驟執行的多了肯定會影響效率的。
類中有乙個const或者引用成員,則類的合成拷貝賦值運算子也定義為刪除的。
我們在寫c++**時,需要注意很多情況,像指標,引用,const這些關鍵字宣告的變數都可能有很多陷阱。比如const物件作為成員變數,在賦值時就是錯誤的,所以預設的拷貝建構函式是無法解決的,編譯器也就不會定義。同樣,對於乙個引用型別的成員變數,你即使給其賦值,只是改變引用原來繫結物件的初始值(引用初始化時必須繫結物件,而且始終繫結這個物件),這很可能不是我們的初衷,我們一般是想改變其所繫結的物件。所以預設的賦值運算子也是不存在的。
直接初始化與拷貝 複製 初始化
std set和std map都有乙個insert和emplace成員函式,那麼,他們的區別是什麼呢?他們都往 set或map 裡增加乙個元素,區別在於新元素的構造上。emplace 使用直接構造,insert 使用複製 拷貝 構造。那麼直接構造和複製構造有什麼區別呢?認識這兩種初始化 構造 有助於...
c 直接初始化與拷貝初始化
我們常見的幾種初始化的形式 string str1 first 拷貝初始化,編譯器允許把這句話改寫為string str first 但是string類必須有public的拷貝 移動 建構函式 string str2 10,a 直接初始化 string str3 str2 直接初始化 string ...
直接初始化和拷貝初始化
定義 示例 string dots 10,直接初始化 string s dots 直接初始化 string s2 dots 拷貝初始化 string null book 9 999 99999 9 拷貝初始化 string nines string 100,9 拷貝初始化注 直接初始化實際上是要求編...