簡體   English   中英

為什么要使用復制構造函數C ++

[英]Why to use copy constructor C++

據我所知,當我們分配一個對象是另一個默認副本構造函數將被調用。

class class1 obj1;
class class2 obj2;
obj1(obj2); //default copy constructor will be called by compiler 

那么,什么時候應該顯式地編寫副本構造函數?

在您的情況下,將調用復制分配運算符,而不是復制構造函數。 要調用復制構造函數,您必須執行例如

class1 obj1;
class1 obj2 = obj1;  // Invokes the copy-constructor in obj2

當編寫復制構造函數(或復制分配運算符或析構函數)時,一個好主意可以通過閱讀3規則來了解。 簡而言之,如果您具有析構函數,復制構造函數或復制賦值運算符中的任何一個,那么您可能應該全部擁有。


此外,盡管如果您不提供自己的編譯器,編譯器會自動為您生成copy-constructor和copy-assignment運算符,但您必須記住,這些自動生成的函數只會進行淺表復制。 如果您在對象中分配了例如指向內存的指針,則自動生成的函數將僅復制實際指針,而不復制其指向的指針。 這意味着在復制后,您將擁有兩個都指向同一內存的對象。 如果delete析構函數中的指針,並且其中一個對象被破壞,則另一個對象仍將具有其指針,但是現在它指向已刪除的內存。

如果不編寫三個或五個類別中的任何一個,則無需編寫任何一個,便會得到默認的復制構造函數:析構函數,復制或移動賦值或構造函數。

有時,這樣做是正確的。 例如,如果您只需要淺表副本,或者該成員的相應函數具有正確的用途,例如智能指針。

如果對象在分配之前存在,那么它不涉及構造,而是分配運算符,簽名為:

T& operator=( T const & ); // from l-value ref
T& operator=( T && ); // from r-value ref, since c++11

一種常見的策略是將賦值運算符編寫為慣用語“復制和交換”:

T& operator=( T const & o ) {
    T val( o );    // you need to write the copy ctor
    swap(*this,o); // you need to write the swap
    return *this;
}
T& operator=( T && o ) {
    T val( std::move(o) );    // you need to write the move ctor
    swap(*this,o); // you need to write the swap
    return *this;
}

該策略的C ++ 11版本

T& operator=( T o ) noexcept { // copy done before the operator that can be noexcept ( swap have to too)
    swap(*this,o); // you need to write the swap
    return *this;
}

在某些情況下,您會發現復制對象的方式並不簡單。 如果您考慮上課:

class Car {
 string BrandName;
 int NumberOfPassenger;
}

顯然,當您要復制兩個對象時,您只想逐個成員地復制它們。 這里沒有什么特別的事情,因此defaut復制構造函數可以正常工作。

但是,假設該類是:

class Car {
 string BrandName;
 int NumberOfPassenger;
 Mechanics EngineeringStuff;
}

在這里,力學是參考類型。 復制構造函數將要做的只是將引用復制到新對象,因此car1和car2這兩個car將共享相同的EngineeringStuff。 但是更自然的行為是執行復制時手動分配新的Mechanics對象,因此汽車不會共享相同的車輪,馬達等。

更一般而言,通常是在必須處理引用類型或某種類型的業務邏輯時,才需要顯式地編寫副本構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM