// 클래스가내부적으로포인터를가지면소멸자에delete 하라.!

 

// 1. 얕은복사(Shallow Copy) 현상. 해결책3가지.

//             (A). 깊은복사(Deep Copy)

//             (B). 복사를금지한다. - private에선언만제공한다.

//             (C). Referece Counting - 속도가조금빨라진다.
//               (
멀리스레드에서는오히려속도가느려진다. 동기화)



http://www.research.att.com/~bs/string_example.c
 // 창시자 코드!!

#include <iostream>

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"

}

 

Tag |

Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다