共用方式為


複製建構函式和複製指派運算子 (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 的值,指派會成功。

如需多載指派運算子的詳細資訊,請參閱指派