定义复制控制函数最为困难的部分通常在于认识到它们的必要性.
---------<<C++Primer中文版(第4版)>>P441
分配内存或其他资源的类几乎总是需要定义复制控制成员来管理所分配的资源。如果一个类需要析构函数,则它几乎也总是需要定义复制构造函数和赋值操作符。
下面这个小程序使用自定义的String类,并显式的定义复制构造函数,重载赋值运算符,和给出析构函数以达到精确控制类的基本行为的目的。
1
String s = "hello";
String t;
String k = s; //调用了显式的复制构造函数
t = s; //调用显式的重载的赋值运算符
t[0] = 'j';
如果没有显示的提供这些行为的控制,当t[0]第一个字母被改动时,s的第一个字幕也将改变,因为他们共享”hello”在堆上的内存区域。这就是所谓的”浅拷贝”。
显式的定义复制构造函数,重载赋值运算符能精确到达控制类的行为的目的,这里我们需要t的改变不影响到s,也就是所谓的”深拷贝”.
2
还有一点要注意的是就是String k = s;时,这里的=号并不是被当重载的赋值运算符号,也就是说在定义类的新对象时候,= 不被当作是重载的赋值运算符。
只是调用了类的复制构造函数String(const & String);
#include <cstddef> #include <iostream>
//参考资料<<C和C++代码精粹>>第20章
using namespace std;
class String { public: String() { count = 0; data=""; }; String(const String&); //复制构造函数 String& String::operator=(const String& s); //重载赋值运算符 (这三者应该同时显式定义) ~String(); //析构函数 String(const char*); char& operator[] (size_t pos); friend ostream& operator<<(ostream&,const String&); private: char* data; size_t count; void clone(const char*); };
inline String::String(const char *s) { clone(s); }
inline String::~String() { delete [] data; }
inline char& String::operator[](size_t pos) { //在inline函数不写return也不会报错?(070406) return data[pos]; }
//显式的复制构造函数定义 String::String(const String& s) { clone(s.data); }
//显示的赋值操作符重载 String& String::operator=(const String& s) { if (this!=&s) { delete[] data; clone(s.data); } return *this; }
ostream& operator<<(ostream& os, const String& s) { os.write(s.data,s.count); return os; }
void String::clone(const char*s) { count = strlen(s); data = new char[count+1]; strcpy(data,s); }
int main(int argc,int argv[]) { String s = "hello"; String t; String k = s; //调用了显式的复制构造函数 t = s; //调用显式的重载的赋值运算符 t[0] = 'j'; //深拷贝 cout << "S == " << s << endl; cout << "t == " << t << endl; return 0; }
|
下面这个程序说明了在我们没有显式定义复制构造函数,赋值运算符时,编译器会为我们提供隐式的
#include <iostream> #include <string> #include <cstdio>
using namespace std;
class MemberA { private: string name; public: MemberA(string& _name) throw(); ~MemberA() throw(); //编译器在此添加隐藏的拷贝构造函数和赋值操作 };
MemberA::MemberA(string& _name) throw() { name = _name; cout << "constructing " << name << "!/n"; }
MemberA::~MemberA() throw() { cout << "deconstruct " << name << "!/n"; }
class MemberB { private: string name; public: MemberB(string& _name) throw(); ~MemberB() throw(); MemberB(const MemberB&) throw(); //覆盖默认拷贝操作 MemberB& operator= (const MemberB&) throw(); //覆盖默认赋值操作 };
MemberB::MemberB(string& _name) throw() { name = _name; cout << "constructing " << name << "!/n"; }
MemberB::MemberB(const MemberB& member) throw() { name = member.name; cout << "copying a Member/n"; }
MemberB::~MemberB() throw() { cout << "deconstruct " << name << "!/n"; }
MemberB& MemberB::operator= (const MemberB&) throw(){ cout << "assigning a Member/n"; return *this; }
int main() { { cout << "调用编译器提供的默认赋值操作的memberA "; string s1("A"); string s2("B"); string s3("C"); MemberA a(s1); MemberA b(s2); MemberA c(s3); c = a; }
{ cout << "调用编译器提供的默认拷贝操作的memberA"; string s1("A"); string s2("B"); string s3("C"); MemberA a(s1); MemberA b(s2); MemberA c = a; }
{ cout << "调用自定义赋值操作(覆盖编译器默认赋值操作)的memberB "; string s1("A"); string s2("B"); string s3("C"); MemberB a(s1); MemberB b(s2); MemberB c(s3); c = a; }
{ cout << "调用自定义拷贝操作(覆盖编译器默认拷贝操作)memberB"; string s1("A"); string s2("B"); string s3("C"); MemberB a(s1); MemberB b(s2); MemberB c = a; }
system("pause"); }
|