写时拷贝COW(copy-on-write)
写时拷贝技术是通过"引用计数"实现的,在分配空间的时候多分配4个字节,用来记录有多少个指针指向块空间,当有新的指针指向这块空间时,引用计数加一,当要释放这块空间时,引用计数减一(假装释放),直到引用计数减为0时才真的释放掉这块空间。当有的指针要改变这块空间的值时,再为这个指针分配自己的空间(注意这时引用计数的变化,旧的空间的引用计数减一,新分配的空间引用计数加一)。
#include<iostream> #include<new.h> #include<string> using namespace std; //1解决内存泄漏 //2编写赋值语句 //3写时拷贝 class String; ostream& operator<<(ostream &out, const String &s); ///////////////////////////////////////////////////////////////////// class String_rep { friend class String; friend ostream& operator<<(ostream &out, const String &s); private: String_rep(const char *str = "") : use_count_(0) { if (str == NULL) { data = new char[1]; data[0] = '\0'; } else { data = new char[strlen(str) + 1]; strcpy(data, str); } } String_rep(const String_rep &rep) { this->data = rep.data; } String_rep& operator=(const String_rep &rep) { this->data = rep.data; } ~String_rep() { if (data != NULL) { delete[]data; data = NULL; } } public: void increment() { ++use_count_; } void decrement() { //引用计数为0,释放共享内存 if (--use_count_ == 0) delete this; } private: char *data; int use_count_; }; ////////////////////////////////////////////////////// class String { friend ostream& operator<<(ostream& out, const String &s); public: String(const char *str = "") :rep(new String_rep(str)) { rep->increment(); } String(const String &s) { rep = s.rep; rep->increment(); } String& operator=(const String &s) { if (&s != this) { this->rep->decrement(); //原有共享内存中的引用计数减一 this->rep = s.rep; this->rep->increment(); //现有引用计数加一 } return *this; } ~String() { //String析构一次,引用计数减一 rep->decrement(); } public: void to_upper(); String& operator+=(const String &str); private: String_rep *rep; }; ///////////////////////////////////////////////////////////////////////// ostream& operator<<(ostream &out, const String &s) { out << s.rep->data; return out; } //创建新的共享内存原来共享内存中值一样,然后再修改 void String::to_upper() { String *newStr = new String(this->rep->data); this->rep->decrement(); this->rep = newStr->rep; this->rep->increment(); char *str = this->rep->data; while (*str != '\0') { *str -= 32; ++str; } delete newStr; } String& String::operator+=(const String &str) { char *ch = new char[strlen(str.rep->data) + strlen(this->rep->data) + 1]; strcpy(ch,this->rep->data); strcat(ch, str.rep->data); this->rep->decrement(); String_rep *s = new String_rep(ch); this->rep = s; this->rep->increment(); return *this; } int main() { String s("abc"); String s1; s1 = s; // String s2("xyz"); String s3(s); s2.to_upper(); s3 += s2; cout << s2 << endl; cout << s3 << endl; return 0; }