<span style="font-family:Microsoft YaHei;">#include <iostream>
using namespace std;
class String {
public:
String() ;
String(const String &other) ;
~String() ;
String & operator = (const String &other) ;
private:
char *m_data;
int val;
};</span>
位拷贝和值拷贝
构造函数、析构函数、赋值函数是每个类最基本的函数。每个类只有一个析构函数和一个赋值函数。但有很两个构造函数,一个为拷贝构造函数,其他为普通构造函数。
对于一个类,如果不编写这四个函数,C++编译器将自动为A产生四个默认函数。那么既然能自动生成函数,为什么还要自定义?原因之一是默认的拷贝构造函数和默认的赋值函数都采用的是位拷贝而非值拷贝。
位拷贝拷贝的是地址,值拷贝拷贝的是内容。
在上面定义的String类里,如果定义两个String的对象a和b。当利用位拷贝时,a = b,其中a.val = b.val; 这个没问题
但是a.m_data = b.m_data就错了,a.m_data 和b.m_data作为指针将指向同一个区域。这样出现问题:
1. a.m_data 原来的内存区域未释放,造成内存泄露
2. a.m_data和b.m_data指向同一块区域,任何一方改变将会影响到另一方
3. 当对象释放时,b.m_data会释放两次
因此
当类中含有指针变量时,默认拷贝构造函数和默认赋值函数由于使用位拷贝就隐含了错误,这时需要自己定义。
结论
1. 有一中特别常见的情况需要自己定义拷贝构造函数:类具有指针函数
2. 赋值操作符和拷贝构造函数可以看成一个单元,当需要其中一个时,我们几乎也肯定需要另一个
3. 三法则:如果类需要析构函数,则它也需要赋值操作符和拷贝构造函数
注意
1. 如果没有定义拷贝构造函数,编译器会自动生成默认的拷贝构造函数
2. 如果定义了其他构造函数,包括拷贝构造函数,编译器绝不会生成默认构造函数
3. 即使自己写了析构函数,编译器也会自动生成默认析构函数
拷贝构造函数 VS 赋值函数
/*
* copy.cpp
*
* Created on: 2015?8?5?
* Author: nanzhou
*/
#include <iostream>
using namespace std;
class String {
public:
String(const char *str) ;
String(const String &other) ;
~String() ;
String & operator = (const String &other) ;
private:
char *m_data;
};
String::String(const char *str) {
cout << "zidingyi Constructor" << endl;
if (NULL == str) {
m_data = new char[1];
*m_data = '\0';
}
else {
int length = strlen(str);
m_data = new char[length + 1];
strcpy(m_data, str);
}
}
String::String(const String &other) {
cout << "zidingyi Copy Constructor" << endl;
int length = strlen(other.m_data);
m_data = new char[length + 1];
strcpy(m_data, other.m_data);
}
String & String::operator = (const String &other) {
cout << "zidingyi fuzhi function" << endl;
if ( this == &other) {
return *this;
}
else {
delete [] m_data;
int length = strlen(other.m_data);
m_data = new char[lenght + 1];
strcpy (m_data, other.m_data);
return *this;
}
}
String::~String() {
cout << "zidingyi xigou function" << endl;
delete [] m_data;
}
int main() {
cout << "a(\"abc\")" << endl;
String a("abc");
cout << "b(\"cde\")" << endl;
String b("cde");
cout << " d = a " << endl;
String d = a;
cout << "c = a" << endl;
String c(b);
cout << " c = a " << endl;
c = a;
cout<<endl;
}
1. 赋值函数中,上来比较this == &other是很必要的,要防止自身复制,这是很危险的,因为下面有delete []m_data,如果提前把m_data释放了,指针就成了野指针,再赋值就错了。