2014-04-18 31 views
1

我想改善我對複製構造函數和複製分配的理解。運營商 這裏是我想出了可以將此作業和複製cnstr更好地組織

class Bar 
{ 
    char* name; 
    int zip; 
    std::string address; 

    public: 
    Bar(const Bar& that) 
    { 
      //Copy constructor 
      size_t len = strlen(that.name + 1); 
      name = new char[len]; 
      strcpy(name, that.name); 

      //Copy the zip 
      this->zip = that.zip; 

      //Copy the address 
      this->address = that.address; 
    } 
    Bar& operator=(const Bar& that) 
    { 
     //Assignment operator 
     if(this != &that) 
     { 
      //Copy the name 
      size_t len = strlen(that.name + 1); 
      name = new char[len]; 
      strcpy(name, that.name); 

      //Copy the zip 
      this->zip = that.zip; 

      //Copy the address 
      this->address = that.address; 

     } 
     return *this; 
    } 
}; 

一個簡單的類我的問題是因爲在拷貝構造函數的代碼,拷貝賦值操作符是相同的它更有意義的統一是陷入了深深的複製方法,以便那incase我添加另一個成員變量我不必添加另一行到複製cnstr和複製分配。部分 ?有什麼建議麼 ?

+1

爲什麼你不使用'std :: String? –

+0

@EdHeal:他是,再次檢查:P –

+0

我正在使用兩者。以防萬一我遇到'char *'我也決定使用它。 – Rajeshwar

回答

2

做,你管理自己的資源的事物的「正常」的方式有一點不同:

char* cppstrdup(const char*s, int len=0); 
class Bar 
{ 
    char* name; 
    int zip; 
    std::string address;  
public: 
    Bar(const Bar& that) 
     :name(nullptr), 
     zip(that->zip), 
     address(that->address) 
    { 
     name = cppstrdup(that.name); //done here for exception safety reasons 
    } 
    Bar(Bar&& that) //if you have C++11 then you'll want this too 
     :name(nullptr) 
    { 
     swap(*this,that); 
    } 
    ~Bar() //you forgot the destructor 
    { 
     delete [] name; 
    } 
    Bar& operator=(Bar that) //this is called copy and swap. 
    { //"that" is a copy (notice, no & above), and we simply swap 
     swap(*this,that); 
     return *this; 
    } 
    friend void swap(Bar& left, Bar& right) 
    { 
     using std::swap; 
     swap(left.name, right.name); 
     swap(left.zip, right.zip); 
     swap(left.address, right.address); 
    } 
}; 
//uses new instead of malloc 
inline char* cppstrdup(const char* s, int len) 
{ 
    if (s==0) return nullptr; 
    if (len==0) len = strlen(s); 
    char* r = new char[len+1]; 
    strncpy(r, len+1, s); 
    r[len] = 0; 
    return r; 
} 

這種模式的好處是,獲得異常安全性要容易得多,通常具有強大的例外保證。

當然,更正常的是不使用char*這個名字,並且服從「零規則」是不變的。在這種情況下,它變得非常不同:

class Bar 
{ 
    std::string name; 
    int zip; 
    std::string address; 

public: 
    Bar() = default; //well, that's easy 
}; 
+0

如果你打算將C++ 11添加到它,你是否也可以給出移動賦值運算符 – Rajeshwar

+0

@Rajeshwar的工作:是的,我認爲移動構造函數太簡單了。接得好。作爲朋友的'swap'使其不在全局名稱空間中,這使得錯誤消息更簡單,並且還允許它訪問需要工作的私有成員。 –

+0

謝謝,這是有道理的。最後一個問題,如果'Bar'派生並且有一個基類說'BaseBar'我們將如何處理交換方法? – Rajeshwar

0

檢查COPY & SWAP成語。總之 - 你的邏輯進入拷貝構造函數和交換方法和你的賦值運算符是這樣的:

Bar& operator=(const Bar& that) 
{ 
    Bar temp(that); 
    swap(*this, temp); 
    return *this; 
} 
+0

爲什麼不能有'那'是副本而不是'臨時'? –

+1

這個叫什麼'swap'?我不認爲你想要通用的'std :: swap' –