// 클래스가내부적으로포인터를가지면소멸자에delete 하라.!
// 1. 얕은복사(Shallow Copy) 현상. 해결책3가지.
// (A). 깊은복사(Deep Copy)
// (B). 복사를금지한다. - private에선언만제공한다.
// (C). Referece Counting - 속도가조금빨라진다.
// ( 멀리스레드에서는오히려속도가느려진다. 동기화)
http://www.research.att.com/~bs/string_example.c // 창시자 코드!!
#include
using namespace std;
class String
{
//////////////////////////////////////////////////////////////////////////
struct SRep // 내포클래스: String에서만이클래스를사용하므로내부에넣어버리자!!
{
char* buff;
int sz;
int ref;
SRep(int nsz, const char* pbuff)
{
ref = 1;
sz = nsz;
buff = new char[sz+1]; // add space for terminator
strcpy( buff, pbuff );
}
SRep( const char* s ) : ref(1)
{
sz = strlen(s);
buff = new char[sz+1];
strcpy( buff, s );
}
~SRep() { delete[] buff; }
SRep* get_own_copy()
{
if ( ref == 1 ) return this;
ref--;
return new SRep( sz , buff );
}
void assign(int nsz, const char* pbuff)
{
if (sz != nsz) {
delete[] buff;
sz = nsz;
buff = new char[sz+1];
}
strcpy( buff ,pbuff );
}
private:
SRep(const SRep&);
SRep& operator=(const SRep&);
};
//////////////////////////////////////////////////////////////////////////
class Cref
{
friend class String;
String& s;
int i;
Cref(String& _s, int _i) : s(_s), i(_i) { }
Cref(const Cref& r) : s(r.s), i(r.i) { }
Cref(); // not defined, never used
public:
operator char() const
{
s.check(i); return s.read(i);
}
void operator=(char c)
{
s.write(i,c);
}
};
//////////////////////////////////////////////////////////////////////////
SRep* rep;
public:
class Range {};
String()
{
rep = new SRep(0,"");
}
String( const char* s ) { rep = new SRep(s); }
~String() { if( --(rep->ref) == 0 ) delete rep; }
// 참조개수기반의복사생성자
String( const String& s )
{
rep = s.rep;
++(rep->ref);
}
//////////////////////////////////////////////////////////////////////////
// 참조개수기반의대입연산자
String& operator=( const String& s )
{
// 모든대입연산자의기본은1번째줄에서자신과의참조를비교해야한다.
if( &s == this ) return *this;
if( --(rep->ref) == 0 ) delete rep;
rep = s.rep;
// 이제count 증가.
++(rep->ref);
return *this;
}
friend ostream& operator<<( ostream& os, const String& s)
{
return os << s.rep->buff;
}
char operator[](int i) const
{
check(i);
return rep->buff[i];
}
Cref String::operator[](int i)
{
check(i);
return Cref(*this,i);
}
String& operator=(const char* s)
{
if (rep->ref == 1)
rep->assign(strlen(s),s);
else {
rep->ref--;
rep = new SRep(strlen(s),s);
}
return *this;
}
//////////////////////////////////////////////////////////////////////////
void check(int i) const
{
if (i<0 || rep->sz<=i) throw Range();
}
char read(int i) const
{
return rep->buff[i];
}
void write(int i, char c)
{
rep=rep->get_own_copy();
rep->buff[i] = c;
}
};
void main()
{
String s1 = "hello";
String s2 = s1;
char c = s1[1]; // s1.operator[](1)
cout << c << endl; // 'e'가나오면된다.
s1[1] = 'A'; // s1, s2는서로다른"hello" 메모리를사용해야한다.
cout << s1 << endl; // "hAllo"
cout << s2 << endl; // "hello"
}