保证写时(修改,覆盖)进行深拷贝,复制进行浅拷贝,通过引用计数管理内存空间。
cow.h
#ifndef COW_H
#define COW_H
#include <iostream>
#include <cstddef>
using namespace std;
class PstrRefcnt;
class ProxyChar;
class Cow_String {
friend class ProxyChar;
friend istream &operator>>(istream &, Cow_String &);
friend ostream &operator<<(ostream &, const Cow_String &);
public:
Cow_String(const char *str = "");
Cow_String(const Cow_String &);
Cow_String &operator=(const char *);
Cow_String &operator=(const Cow_String &);
ProxyChar operator[](size_t);
const char *get_pstr() const;
size_t get_refCnt() const;
size_t get_size() const;
size_t get_capacity() const;
~Cow_String();
private:
PstrRefcnt *_pprc;
};
class ProxyChar {
friend istream &operator>>(istream &, ProxyChar &&);
friend ostream &operator<<(ostream &, ProxyChar &&);
public:
ProxyChar(Cow_String &, size_t);
ProxyChar &operator=(char c);
ProxyChar &operator=(const ProxyChar &);
operator char() const;
private:
Cow_String &_cowStr;
size_t _index;
};
#endif
cow.cpp
#include "cow.h"
#include <cstring>
/* class PstrRefcnt */
class PstrRefcnt {
friend ostream &operator<<(ostream &, const PstrRefcnt &);
public:
PstrRefcnt(const char *);
PstrRefcnt(const PstrRefcnt &);
inline void increaseRefcnt();
inline void decreaseRefcnt();
inline void shouldDelete();
inline char *get_pstr() const;
inline size_t get_refCnt() const;
inline size_t get_size() const;
inline size_t get_capacity() const;
~PstrRefcnt();
private:
size_t _refCnt;
size_t _size;
size_t _capacity;
char *_pstr;
};
PstrRefcnt::PstrRefcnt(const char *str)
: _size(strlen(str)), _capacity(_size + 1), _refCnt(0), _pstr(new char[_capacity]) {
strcpy(_pstr, str);
increaseRefcnt();
}
PstrRefcnt::PstrRefcnt(const PstrRefcnt &other)
: _size(other._size), _capacity(_size + 1), _refCnt(0), _pstr(new char[_capacity]) {
strcpy(_pstr, other._pstr);
increaseRefcnt();
}
void PstrRefcnt::increaseRefcnt() {
_refCnt++;
}
void PstrRefcnt::decreaseRefcnt() {
_refCnt--;
}
void PstrRefcnt::shouldDelete() {
decreaseRefcnt();
if (_refCnt == 0) {
delete this;
}
}
char *PstrRefcnt::get_pstr() const {
return _pstr;
}
size_t PstrRefcnt::get_refCnt() const {
return _refCnt;
}
size_t PstrRefcnt::get_size() const {
return _size;
}
size_t PstrRefcnt::get_capacity() const {
return _capacity;
}
PstrRefcnt::~PstrRefcnt() {
if (_pstr) {
cout << *this << " " << "~PstrRefcnt()" << endl;
delete[] _pstr;
_pstr = nullptr;
}
}
ostream &operator<<(ostream &os, const PstrRefcnt &prc) {
os << prc._pstr;
return os;
}
/* class PstrRefcnt */
/* class ProxyChar */
ProxyChar::ProxyChar(Cow_String &cowStr, size_t index)
: _cowStr(cowStr), _index(index) {
}
ProxyChar &ProxyChar::operator=(const char c) {
if(_cowStr.get_pstr()[_index] != c && _cowStr.get_refCnt() > 1){
_cowStr._pprc->shouldDelete();
_cowStr._pprc = new PstrRefcnt(*_cowStr._pprc);
}
_cowStr._pprc->get_pstr()[_index] = c;
return *this;
}
ProxyChar &ProxyChar::operator=(const ProxyChar &other) {
*this = static_cast<char>(other);
return *this;
}
ProxyChar::operator char() const {
return _cowStr.get_pstr()[_index];
}
istream &operator>>(istream &is, ProxyChar &&prc) {
char c;
is >> c;
prc = c;
return is;
}
ostream &operator<<(ostream &os, ProxyChar &&prc) {
os << prc._cowStr.get_pstr()[prc._index];
return os;
}
/* class ProxyChar */
/* class Cow_String */
Cow_String::Cow_String(const char *str)
: _pprc(new PstrRefcnt(str)) {
}
Cow_String::Cow_String(const Cow_String &other)
: _pprc(other._pprc) {
_pprc->increaseRefcnt();
}
Cow_String &Cow_String::operator=(const char *str) {
if (strcmp(get_pstr(), str) != 0) {
_pprc->shouldDelete();
_pprc = new PstrRefcnt(str);
}
return *this;
}
Cow_String &Cow_String::operator=(const Cow_String &other) {
if (this != &other) {
_pprc->shouldDelete();
_pprc = other._pprc;
_pprc->increaseRefcnt();
}
return *this;
}
ProxyChar Cow_String::operator[](size_t index) {
return ProxyChar{*this, index};
}
const char *Cow_String::get_pstr() const {
return _pprc->get_pstr();
}
size_t Cow_String::get_refCnt() const {
return _pprc->get_refCnt();
}
size_t Cow_String::get_capacity() const {
return _pprc->get_capacity();
}
size_t Cow_String::get_size() const {
return _pprc->get_size();
}
Cow_String::~Cow_String(){
_pprc->shouldDelete();
}
istream &operator>>(istream &is, Cow_String &cowString) {
char buffer[1024];
is >> buffer;
cowString._pprc->shouldDelete();
cowString._pprc = new PstrRefcnt(buffer);
return is;
}
ostream &operator<<(ostream &os, const Cow_String &cowString) {
os << *cowString._pprc;
return os;
}
/* class Cow_String */
main.cpp
#include "cow.h"
void test(){
Cow_String s1 = "MikuMiku";
Cow_String s2 = s1;
Cow_String s3, s4;
cout << "s1: " << s1; //预期输出MikuMiku
cout << " s1.refcnt: " << s1.get_refCnt() << endl; //预期输出2
s4 = s3 = s1; //这里析构两次
cout << "s1: " << s1; //预期输出MikuMiku
cout << " s1.refcnt: " << s1.get_refCnt() << endl; //预期输出4
s1[1] = 'o';
s2[2] = 'o';
s3[3] = s2[2];
cin >> s4[4]; //输入o
cout << s4[s4.get_size()-1] << endl; //预期输出u
cout << "s1: " << s1; //预期输出MokuMiku
cout << " s1.refcnt: " << s1.get_refCnt() << endl; //预期输出1
cout << "s2: " << s2; //预期输出MiouMiku
cout << " s2.refcnt: " << s2.get_refCnt() << endl; //预期输出1
cout << "s3: " << s3; //预期输出MikoMiku
cout << " s3.refcnt: " << s3.get_refCnt() << endl; //预期输出1
cout << "s4: " << s4; //预期输出Mikuoiku
cout << " s4.refcnt: " << s4.get_refCnt() << endl; //预期输出1
//结束析构四次
}
int main(){
test();
return 0;
}
g++ main.cpp cow.cpp
./a.out
运行结果:
s1: MikuMiku s1.refcnt: 2
~PstrRefcnt()
~PstrRefcnt()
s1: MikuMiku s1.refcnt: 4
o
u
s1: MokuMiku s1.refcnt: 1
s2: MiouMiku s2.refcnt: 1
s3: MikoMiku s3.refcnt: 1
s4: Mikuoiku s4.refcnt: 1
Mikuoiku ~PstrRefcnt()
MikoMiku ~PstrRefcnt()
MiouMiku ~PstrRefcnt()
MokuMiku ~PstrRefcnt()进程已结束,退出代码为 0