스마트포인터

1. 스마트포인터를 이용하면 객체의 공유, 카운트 관리, 포인터를 관리 하는데 있어 편리하다.

구현된 소스를 가지고 사용 방법과 실행 결과를 먼저 설명한다.

#include <iostream>

#include "MyRTTI.h"

#include "MyRefObj.h"

 

class   CCar : public   MyRefObj

{

    MyDeclareRTTI;

 

public:

    void Show() {    std::cout << "This is Car." << std::endl;  }

};

 

MySmartPointer( CCar );

MyImplementBaseRTTI(CCar);

 

void main()

{

    CCarPtr spCar1;

    {

        CCarPtr spCar2;

        {

            CCarPtr spCar = new CCar;  //spCar의 참조 카운터 1

            spCar1 = spCar;   //참조 카운터 2

            spCar1 = 0;       //참조 카운터 1

            spCar2 = spCar;   //참조 카운터 2

            spCar = 0;        //참조 카운터 1

        }

    }

}   

<<스마터 포인터를 사용 방법>>

1. 참조 갯수를 관리하는 MyRefObj 클래스를 상속한다.

2. 스마터 포인터를 매크로를 이용해 스마터 포인터 클래스를 선언한다.

MySmartPointer(  CCar )

MySmartPointer()안에 사용 하고자 하는 클래스 이름을 넣는다.

<<실행 결과>>

위의 소스에서 spCar의 참조 카운터는 주석과 같다.

객체 생성시에 1,
다른 포인터에 참조 될 때 2,
다른 포인터에 0을 넣으면 1
spCar = 0을 실행한후 spCar2에 포인터는 계속 살아 있다.
spCar2가 spCar를 참조 했기 때문에, 실제 데이터는 계속 유지 되는 것이다.

스마터 포인터의 데이터는 참조 카운터가 0인 경우 객체 삭제가 일어 난다.
스마터 포인터의 데이터를 지우기 위해 delete를 실행 하면, 객체의 삭제는 삭제 하지 않으니 조심하기 바란다.

구차니로 인해 일부 소스만 리스트로 올린다.

//MyRefObj.h

#ifndef __MYREFOBJ_H

#define __MYREFOBJ_H

 

#include "MyRTTI.h"

#include "MySmartPointer.h"

 

class MyRefObj

{

    MyDeclareRTTI;

 

public:

    virtual ~MyRefObj ();

 

    void    IncRef();

    void    DecRef();

    int     GetRefCount();

    static unsigned int GetTotalObject();

 

protected:

    // construction (abstract base class)

    MyRefObj();

 

    int                        m_iRef;

    static unsigned int        ms_uiTotalObject;

};

 

MySmartPointer( MyRefObj );

 

//----------------------------------------------------------------------------

inline void MyRefObj::IncRef()

{

    m_iRef++;

}

//----------------------------------------------------------------------------

inline void MyRefObj::DecRef()

{

    m_iRef--;

}

//----------------------------------------------------------------------------

inline int MyRefObj::GetRefCount()

{

    return m_iRef;

}

 

 

#endif

 

//MySmartPointer.h

 

#ifndef __MYSMARTPOINTER_H

#define __MYSMARTPOINTER_H

 

#include "MySmartPointerMacro.h"

 

 

template <class T>

class MyPointer

{

public:

    // construction and destruction

    MyPointer (T* pkObject = 0);

    MyPointer (const MyPointer& rkPointer);

    ~MyPointer ();

 

    // implicit conversions

    operator T* () const;

    T& operator* () const;

    T* operator-> () const;

 

    // assignment

    MyPointer& operator= (const MyPointer& rkReference);

    MyPointer& operator= (T* pkObject);

 

    // comparisons

    bool operator== (T* pkObject) const;

    bool operator!= (T* pkObject) const;

    bool operator== (const MyPointer& rkReference) const;

    bool operator!= (const MyPointer& rkReference) const;

 

protected:

    void DecRefObject();

 

protected:

    // the shared object

    T* m_pkObject;

};

 

#include "MySmartPointer.inl"

 

#endif

 

 

// Magic Software, Inc.

// http://www.magic-software.com

// Copyright (c) 2000, All Rights Reserved

//

// Source code from Magic Software is supplied under the terms of a license

// agreement and may not be copied or disclosed except in accordance with the

// terms of that agreement.  The various license agreements may be found at

// the Magic Software web site.  This file is subject to the license

//

// RESTRICTED USE SOURCE CODE

// http://www.magic-software.com/License/restricted.pdf

 

//---------------------------------------------------------------------------

template <class T>

inline MyPointer<T>::MyPointer (T* pkObject)

{

    m_pkObject = pkObject;

    if ( m_pkObject )

        m_pkObject->IncRef();

}

//---------------------------------------------------------------------------

template <class T>

inline MyPointer<T>::MyPointer (const MyPointer& rkPointer)

{

    m_pkObject = rkPointer.m_pkObject;

    if ( m_pkObject )

        m_pkObject->IncRef();

}

//---------------------------------------------------------------------------

template <class T>

inline MyPointer<T>::~MyPointer ()

{

    DecRefObject();

}

//---------------------------------------------------------------------------

template <class T>

inline void MyPointer<T>::DecRefObject()

{

    if ( m_pkObject )

    {

        m_pkObject->DecRef();

        if(m_pkObject->GetRefCount() == 0)

        {

            delete m_pkObject;

            m_pkObject = NULL;

        }

    }

}

//---------------------------------------------------------------------------

template <class T>

inline MyPointer<T>::operator T* () const

{

    return m_pkObject;

}

//---------------------------------------------------------------------------

template <class T>

inline T& MyPointer<T>::operator* () const

{

    return *m_pkObject;

}

//---------------------------------------------------------------------------

template <class T>

inline T* MyPointer<T>::operator-> () const

{

    return m_pkObject;

}

//---------------------------------------------------------------------------

template <class T>

inline MyPointer<T>& MyPointer<T>::operator= (const MyPointer& rkPointer)

{

    if ( m_pkObject != rkPointer.m_pkObject )

    {

        DecRefObject();

        m_pkObject = rkPointer.m_pkObject;

        if ( m_pkObject )

            m_pkObject->IncRef();

    }

    return *this;

}

//---------------------------------------------------------------------------

template <class T>

inline MyPointer<T>& MyPointer<T>::operator= (T* pkObject)

{

    if ( m_pkObject != pkObject )

    {

        DecRefObject();

        m_pkObject = pkObject;

        if ( m_pkObject )

            m_pkObject->IncRef();

    }

    return *this;

}

//---------------------------------------------------------------------------

template <class T>

inline bool MyPointer<T>::operator== (T* pkObject) const

{

    return ( m_pkObject == pkObject );

}

//---------------------------------------------------------------------------

template <class T>

inline bool MyPointer<T>::operator!= (T* pkObject) const

{

    return ( m_pkObject != pkObject );

}

//---------------------------------------------------------------------------

template <class T>

inline bool MyPointer<T>::operator== (const MyPointer& rkPointer) const

{

    return ( m_pkObject == rkPointer.m_pkObject );

}

//---------------------------------------------------------------------------

template <class T>

inline bool MyPointer<T>::operator!= (const MyPointer& rkPointer) const

{

    return ( m_pkObject != rkPointer.m_pkObject );

}

//---------------------------------------------------------------------------

 

//MySmartPointerMacro.h

#ifndef __MYSMARTPOINTERMACRO_H

#define __MYSMARTPOINTERMACRO_H

 

#define MySmartPointer(classname) \

    class classname; \

    typedef MyPointer<classname> classname##Ptr

 

// cast a smart pointer of one type to a pointer of another type.

#define MySmartPointerCast(type,smartptr) ((type*)(void*)(smartptr))

 

#endif

 

소스 : SmartPointer.zip

참조:  3D Game Engine Design, 저자: David H.Eberly