d的複製建構函式

2021-10-02 20:33:32 字數 4706 閱讀 8174

本文件提出了複製建構函式,它是後複製函式的替代方法.複製建構函式消除了對後複製的需求,並修復了其缺陷和固有限制.還討論了演進和向後相容性.

本節重點介紹了後複製存在問題,並說明了為什麼複製建構函式後複製好.

無法有意義地過載或限定後複製函式.但,編譯器不會拒絕限定器應用,如下所示:

構 a

}構 b

}構 c

}

存在限定詞的情況下,未定義後複製的語義,實驗表明該行為是打補丁式的:

常 不能修改目標中的任何欄位的後複製

不變 永遠不呼叫後複製(導致編譯錯誤)

共享 後複製位不能保證原子性

定義和實現有意義語義將破壞在當前語義下經過測試並認為正確的**.

如上所述,不嚴格限制,後複製很難檢查型別,且同步成本過高.

該dip提出具有以下優點的複製構造函式:

該特徵在c++語言上效果很好[3];

可按普通建構函式檢查複製建構函式型別(由於不位複製,字段初始化方式與普通建構函式相同);即按普通建構函式檢查常/不變/共享型別.

提供封裝.

缺點是使用者必須手動複製所有字段,且每次加字段到構時,必須修改複製構造函式.但,使用d的自省機制可輕鬆搞定.如,此簡單**可用作語言習語或庫函式:

foreach

(i,ref field;src.tupleof)

本.tupleof[i]

=字段;

如上所示,可用幾行**輕鬆替換後複製的好處.如下詳述,複製建構函式以最小語言複雜性解決後複製的問題.

本節討論有關複製建構函式語義的所有技術方面.

定義內部,如果函式宣告中第乙個引數與構型別的非預設引用相同,其他所有引數都具預設值時,則為複製建構函式.這種方式宣告複製建構函式,優點是不用改解析器,語法可不變.例:

匯入 std.stdio ;

構 a//複製建構函式

本(引用 中 域 a rhs,

int b =

7)不變

//使用預設引數的複製建構函式

}空 main()

顯式呼叫複製建構函式(如上面的c),因為它也是先前語言語義中存在的建構函式.

引用傳遞複製建構函式的引數,避免無限遞迴(按值傳遞需要複製構,導致無限遞迴呼叫複製構造).注意,如果源是右值,則不需要呼叫複製建構函式,因為將按位移動(如必要)到目標中(即,優先移動構造).例:

構  a 

}a 建立(

)空 main()

僅呼叫乙個複製構造,在rhs位置的.然後,把右值放入.

可對複製構造函式引數/函式本身應用型別限定器,以允許定義跨不同可變級物件拷貝.型別限定器是可選的.

本節討論複製建構函式和其他語言特徵間的語義分析和互動關係.

為確保後複製到複製建構函式的平穩過渡,此dip提出以下策略:如果乙個構定義了(使用者定義或生成的)後複製,則忽略複製建構函式,優先後複製.現有的不使用後複製**庫可開始使用複製建構函式,而當前依賴後複製的**庫可使用複製建構函式開始編寫新**並刪除後複製.本dip建議棄用後複製,但未規定棄用時間表.

從後複製到複製建構函式語義上相近的轉換如下:

//新**

構 a

}//替換現有**

構 a ...

}

每當將構變數複製另乙個相同型別變數時,編譯器隱式插入複製構造函式呼叫:

顯式初化變數時:

構 a

}空 main()

傳遞引數給函式時:

構 a

}空 函式(a a)

空 main()

從函式按值返回引數且無nrvo時:

構 a

}a 函式(

)a a;

a 槍(

)空 main()

引用傳遞複製構造函式引數,僅當源是左值時,降低初始化至複製構造函式呼叫.儘管可**臨時左值宣告至複製建構函式,但本dip不討論繫結右值到左值.

注意,函式返回定義了複製建構函式的構例項且無法nrvo時,在返回前,在呼叫點呼叫複製建構函式.如可nrvo,則刪除複製:

構 a

}a a;

a 函式(

)空 main()

複製建構函式與建構函式的型別檢查[6][7]一樣.

顯式禁用複製建構函式過載:

構 a

}空 main()

為了禁用複製構建,必須禁用所有複製建構函式過載.在上面示例中,僅禁用了從可變到可變的複製;仍可呼叫從不變到可變複製過載.

可用(從合格的源複製的)引數的不同限定器或複製建構函式自身(複製到合格目標)來過載複製建構函式:

構 a

//-可變源,可變目標

本(ref 中 域 不變 a b)

// 2-可變源,可變目標

本(ref 中 域 a b)不變

// 3-可變源,不變目的地

本(引用 中 域 不變 a b)不變

//4不變源不變目標

}空 main()

使使用者能任意組合限定:常,不變,共享,常 共享.

進出用於限定變,常或不變相同的型別:

構 a

}空 main()

部分匹配時,適用現有過載和隱式轉換規則.

如果構未定義複製建構函式,則右邊儲存位置位刷到左邊來初化.例:

構 a

空 main()

構定義複製建構函式時,將對該構禁用所有隱式位刷.例:

構 a

}空 函式(不變 a)

空 main()

構定義別名 本複製建構函式可能衝突.如返回別名 本型別是定義型別的特定版本時,有歧義.例:

構 a

別名 函式 本;

本(引用 中 域 a)不變

}構 b

別名 函式 本;

本(ref 中 域 b b)

}//將這三個屬性合併為乙個.

空 main()

雖然複製建構函式和別名 本都適合解決賦值問題時,複製建構函式比別名 本優先順序更高,因為它更特定(複製建構函式目的就是建立副本).如果未匹配過載集中的複製建構函式,則發出錯誤,即使使用從別名 本理論上講也可生成匹配構造器.即,在複製構造上,忽略別名 本.

如滿足以下所有條件,編譯器對構 s,隱式生成複製建構函式:

s 未顯式宣告任何複製建構函式;

s 至少有乙個定義具有複製建構函式的直接成員,且該成員不與任何其他成員通過重疊.

如滿足上述限制,則生成以下複製建構函式:

本(引用 中 域 進出(s)src)進出

定義複製建構函式的構不是pod.

如果聯 s具有定義複製建構函式的字段,則每當s按複製初化型別物件時,發出錯誤.重疊字段(匿名聯合)也這樣.

按源物件可變引用傳遞複製建構函式的引數.即複製構造函式呼叫可合法修改源物件:

構 a

}空 main()

允許非的引數,不然,太麻煩,還要為引數,裡面再把去掉.折騰.c++不推薦.

構 c

}空 函式(c c)

空 main()

具有上述定義建構函式只用作複製建構函式.

複製建構函式

今天回看了前面的內容,發現這一章掌握的不夠好,就重看了一遍,順便總結一下 無規律總結 複製建構函式用於複製物件,即可以初始化物件,也可以將複製得到的物件作為實參傳遞給函式,多用於初始化。當我們這樣寫 string null bulk 9 9 9 9 在建立null bulk時編譯器先呼叫string...

複製建構函式

拷貝建構函式的標準寫法如下 class base base const base b 上述寫法見得最多,甚至你認為理所當然。那麼如果我們不寫成引用傳遞呢,而是值傳遞,那麼會怎樣?class base base const base b 編譯出錯 error c2652 base illegal co...

複製建構函式

呼叫複製建構函式的情形 在c 中,下面三種物件需要呼叫複製建構函式 1 乙個物件作為函式引數,以值傳遞的方式傳入函式體 2 乙個物件作為函式返回值,以值傳遞的方式從函式返回 3 乙個物件用於給另外乙個物件進行初始化 常稱為賦值初始化 4 編譯器生成臨時物件 一 乙個物件作為函式引數,以值傳遞的方式傳...