编译器会给出默认的拷贝构造、拷贝赋值,但针对指针会有深拷贝浅拷贝的问题,会出现内存泄漏的风险。以String类实现为例。
如果一个类中有指针成员,则必须有拷贝构造和拷贝赋值。因为编译器默认的赋值操作仅仅是浅拷贝。
class String
{
public:
String(const char* cstr = 0); //默认构造
String(const String& str); //拷贝构造
String& operator=(const String& str); //操作符重载,拷贝复制
~String(); //析构
char* get_c_str() const { return m_data; }
private:
char* m_data; //因为字符串有大有小,所以用指针的方式动态分配内存
};
首先对上面BigThree来进行分析。
针对默认构造的分析,首先代码如下:
String::String(const char* cstr = 0)
{
if (cstr)
{
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
}
else {
m_data = new char[1];
*m_data = '\0';
}
}
String::~String
{
delete[] m_data;
}
拷贝构造:
下面代码就是进行深拷贝,浅拷贝如果是只是所有权的改变,有点像别名的意思,因为只对指针进行浅拷贝本质上都是指向一块内存。而深拷贝就是完全的重新拥有,即自己开辟内存,自己存放数据,这样可以避免野指针的出现。
String::String(const String&&& str)
{
m_data = new char[ strlen[str.m_data) + 1 ];
strcpy(m_data ,str.m_data);
}
{
String s1("hello");
String s2(s1);
}
拷贝复制
String& String::operator = (const String& str)
{
if( this == & str)
return *this;
delete[] m_data;
m_data = new char[strlen(str.m_data)+1];
strcpy(m_data,str.m_data);
return *this;
}