// 클래스가내부적으로포인터를가지면소멸자에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"
}