複製建構函式和複製指派運算子 (C++)
注意
從 C++11 開始,語言支援兩種指派:「複製指派」(Copy Assignment) 和「移動指派」(Move Assignment)。 在本文中,除非明確指定,否則「指派」表示複製指派。 如需移動指派的詳細資訊,請參閱移動建構函式和移動指派運算子 (C++)。
指派作業和初始化作業都會導致複製物件。
指派:將某個物件的值指派給另一個物件時,第一個物件就會複製到第二個物件。 因此,此程式碼會將
b
的值複製到a
:Point a, b; ... a = b;
初始化:當您宣告新的物件、依值傳遞函式引數,或從函式傳回值時,就會發生初始化。
您可以定義類別類型物件的「複製」語意。 例如,請參考這個程式碼:
TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;
上述程式碼可能表示「將 FILE1.DAT 的內容複製到 FILE2.DAT」,也可能表示「忽略 FILE2.DAT 並且讓 b
成為 FILE1.DAT 的第二個控制代碼」。您必須將適當的複製語意附加至每一個類別,如下所示:
使用指派運算子
operator=
,可傳回類別類型的參考,並採用一個透過const
參考傳遞的參數,例如ClassName& operator=(const ClassName& x);
。使用複製建構函式。
如果您未宣告複製建構函式,則編譯器會產生一個成員複製建構函式。 同樣地,如果您未宣告複製指派建構函式,則編譯器會產生一個成員複製指派運算子。 宣告複製建構函式不會隱藏編譯器產生的複製指派運算子,反之亦然。 如果您實作其中一個,建議您也實作另一個。 當您實作這兩者時,程式碼的意義會很清楚。
複製建構函式接受 ClassName&
類型的引數,其中 ClassName
是類別的名稱。 例如:
// spec1_copying_class_objects.cpp
class Window
{
public:
Window( const Window& ); // Declare copy constructor.
Window& operator=(const Window& x); // Declare copy assignment.
// ...
};
int main()
{
}
注意
盡可能讓複製建構函式引數的類型為 const ClassName&
。 這樣可避免複製建構函式意外變更複製的來源。 其也可讓您從 const
物件複製。
編譯器產生的複製建構函式
編譯器產生的複製建構函式 (像是使用者定義的複製建構函式) 具有「class-name 參考」類型的單一引數。但是當所有基底類別和成員類別將複製建構函式宣告為接受 const
class-name& 類型的單一引數時例外。 在這種情況下,編譯器所產生複製建構函式的引數也會是 const
。
當複製建構函式的引數類型不是 const
時,藉由複製 const
物件進行初始化就會產生錯誤。 反向執行則不成立:如果引數為 const
,您可以藉由複製不是 const
的物件進行初始化。
編譯器產生的指派運算子會遵循與 const
相同的模式。 除非所有基底和成員類別中的指派運算子都接受 ClassName&
類型的引數,否則這類運算子會接受 const ClassName&
類型的單一引數。 在這種情況下,類別產生的指派運算子會接受 const
引數。
注意
虛擬基底類別是由複製建構函式進行初始化,無論是由編譯器所產生或使用者所定義,只會在建構時初始化一次。
影響類似複製建構函式的影響。 如果引數的類型不是 const
,從 const
物件指派就會產生錯誤。 反向執行則不成立:如果將 const
值指派至不是 const
的值,指派會成功。
如需多載指派運算子的詳細資訊,請參閱指派。