2014-04-18 26 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' –