※ 부스트 라이브러리 설치 (Boost library) 

1. Visual Studio 2005 / 2008

: 도구(tool) - 옵션(option) - 프로젝트(projects) - VC++ 디렉토리(VC++ directories) 선택

- 다음 파일의 디렉토리 표시 (Show directories for)

- 콤보박스에서 포함 파일(include files)에 boost library를 설치한 경로를 추가!


2. Borland C++ Compiler / C++ Builder X

: bcc.exe가 위치하는 폴더 안에 bcc32.cfg 파일을 열어서 boost library를 설치한 디렉토리 경로를 추가!

(ex) -I"C:\development\bcc\include;C:\boost 디렉토리"

-L"C:\development\bcc\lib;C:\boost 디렉토리"

3. GNU C++ Compiler

: 환경변수 CPLUS_INCLUDE_PATH에 boost library를 설치한 디렉토리 경로를 추가!


 



1. auto_ptr

 : 소유권 독점 방식으로 구동되는 스마트 포인터. 복사시 소유권 이전 되는 소유권 독점 방식을 취함.

 : C++ 표준 라이브러리에서 제공

: 소유권 이전 금지 - const 키워드 사용 (ex) const boost::auto_ptr<MyClass> ptq(new MyClass);


 [특징]

- 자동으로 포인터에 할당된 메모리를 해제한다.

- 자동으로 포인터를 초기화한다. (디폴트 생성자)

- 댕글링 포인터 문제를 해결한다.


 

[주의사항]

 - auto_ptr은 STL 컨테이너(vector, list, map, hashtable 등)와 사용할 수 없다.

- auto_ptr은 동적 배열에는 사용할 수 없다.

 - auto_ptr은 힙영역에 동적으로 할당된 메모리에만 적용 가능하다.



 [예제1]


#include <iostream>

#include <memory>

#include <boost/shared_ptr.hpp>


using namespace std;


class Car

{

   public:

       Car();

       ~Car();

       void race();

};


Car::Car()

{

    cout << "생성자" << endl;

}


Car::~Car()

{

    cout << "소멸자" << endl;

}


void Car::race()

{

    cout << "붕붕~!" << endl;

}


boost::shared_ptr<Car> createObject()

{

    return boost::shared_ptr<Car>(new Car());

}


int main(void)

{

    boost::shared_ptr<Car> a;

    boost::shared_ptr<Car> b;

 

    a = createObject();

    b = a;


    b->race();


    if(a.get() != NULL) // 실행되지 않는다. 소유권 이전 후 a는 NULL이 된다.

        a->race();


return 0;

 


2. shared_ptr

: 소유권이 공유되는 방식으로 동작하는 스마트 포인터

: 동일한 객체를 가리키는 스마트 포인터의 개수를 센 후, 이 개수가 0이 될 때 객체를 삭제한다.

 즉, 동일한 객체를 참조하는 모든 스마트 포인터가 자신의 scope를 벗어날 때 공유 객체의 소멸이 결정되는 방식.

: STL 컨테이너에서 사용이 가능하다. (boost library를 반드시 설치하고, include 해야 한다.)


[주요 특징]

: 강한 참조의 성격을 가지고 있다.

 : 쓰레드에 안전하게 설계되어 있다. (그러나 쓰레드의 실행 순서에 따라 영향은 받으므로 설계가 중요!)

: Thread Safety 해제 - 헤더 파일에 " #define BOOST_DISABLE_THREADS "를 적어준다.


  [주의사항]

 - 순환참조를 하면 안된다. (정확히 참조 카운트를 알 수 없기 ?문)

- 이름이 없는 shared_ptr을 사용을 피하는 것이 좋다.

 (이미 동적 할당되어 생성된 객체가 삭제되지 않아서 메모리릭이 발생할 수 있기 때문이다.)


- 스마트 포인터 생성시, 생성자를 직접 호출하거나 명시적 형변환만 가능하다.

(암시적 형변환은 지원하지 않는다.)


 

- 원본 포인터(raw pointer)를 직접 삭제 할 수 없다. (reset(), 재할당 혹은 스마트 포인터가 파괴 될 때 

 자동으로 원본 포인터가 삭제되도록 작성하는 것이 좋다.)


 



[예제1]

 


#include <string>

#include <iostream>

#include <memory>

#include <vector>

#include <boost/shared_ptr.hpp> // shared_ptr을 사용하기 위해서는 반드시 추가해야 한다.


using namespace std;


class Fruit

{

   public:

       Fruit(string name);

       ~Fruit();

       string getName();


   private:

       string name;

};


Fruit::Fruit(string name)

{

    this->name = name;

    cout << this->name + " 생성됨" << endl;

}


Fruit::~Fruit()

{

    cout << this->name + " 소멸됨" << endl;

}


string Fruit::getName()

{

    return name;

}


int main(void)

{

    typedef boost::shared_ptr<Fruit> fruit_sPtr; // 참조 카운팅 방식의 스마트 포인터

    vector<fruit_sPtr> vec;


    fruit_sPtr s = fruit_sPtr(new Fruit("Apple"));


    vec.push_back(fruit_sPtr(new Fruit("pear")));

    vec.push_back(fruit_sPtr(new Fruit("banana")));

    vec.push_back(fruit_sPtr(new Fruit("kiwi")));

    vec.push_back(s);


    cout << (*s).getName() << endl;


    return 0;



[예제 2]


#include <iostream>

#include <string>

#include <memory>

#include <boost/shared_ptr.hpp>


using namespace std;


class Shape

{

   public :

       Shape() {}

       ~Shape() {}

       void draw(string str);

};


void Shape::draw(string str)

{

    cout << str.c_str() << endl;

}


int main(void)

{

    typedef boost::shared_ptr<Shape> ShapePtr;


    Shape* shape1 = new Shape();

    ShapePtr sptr1(shape1);


    sptr1.get()->draw("Circle");


    cout << sptr1.use_count() << endl;  // use_count() : 참조 카운트를 반환한다.


    ShapePtr sptr2 = sptr1;

    cout << sptr1.use_count() << endl;


    sptr1.reset();

    cout << sptr2.use_count() << endl;


    return 0;

}



3. weak_ptr 

 : shared_ptr에서 순환참조로 발생하는 문제를 해결하기 위해서 사용하는 스마트 포인터

 : shared_ptr과는 달리 객체에 대한 소유권을 가지지 않고 객체를 사용한다.

 : 약한 참조의 성질을 가지고 있다.

 (객체가 살아있도록 유지시키지 않고, 단순히 객체가 살아 있는 동안 참조)


: 자신이 가리키는 객체가 실제로 살아있는지 체크할 수 없으므로, 댕글링 포인터가 될 수 있다.(단점)

 (따라서 lock 함수를 사용해서 shared_ptr을 얻어올 때 반드시 리턴값이 NULL(0)인지 체크해야 한다.)


 

[예제]


 

#include <iostream>

#include <memory>

#include <boost/shared_ptr.hpp>

#include <boost/weak_ptr.hpp>


using namespace std;


class Parent;


class Child;


typedef boost::shared_ptr<Parent> parentSPtr;

typedef boost::weak_ptr<Parent> parentWPtr;

typedef boost::shared_ptr<Child> childSPtr;


class Parent

{

   public:

       Parent() { cout << "Parents 생성" << endl; };

       ~Parent() { cout << "Parents 소멸" << endl; };

       void drink() { cout << "맥주를 마신다." << endl; };


       childSPtr kid; 

};


class Child

{

   public:

       Child() { cout << "Child 생성" << endl; };

       ~Child() { cout << "Child 소멸" << endl; };

       void drink();


       parentWPtr father;

};


void Child::drink()

{

    cout << "우유를 마신다." << endl;

    parentSPtr f = father.lock(); // shared_ptr을 얻는다.

 

    if(f) // 객체가 존재하는지 반드시 체크해야 한다.

        f->drink();

}


int main(void)

{

    Child* child = new Child();


    parentSPtr pSptr(new Parent);

    childSPtr cSptr(child);


    cout << "#parent의 참조개수: " << pSptr.use_count() << endl;

    cout << "#child의 참조개수: " << cSptr.use_count() << endl;


    pSptr->kid = cSptr;

    cSptr->father = pSptr;

 

    cout << "#parent의 참조개수: " << pSptr.use_count() << endl;

    cout << "#child의 참조개수: " << cSptr.use_count() << endl;


    cSptr->drink();

    pSptr.reset();


    return 0;

}

 


4. intrusive_ptr

: 참조 개수를 스마트 포인터 안에 두지 않고, 관리할 클래스 안에 보관하는 방식의 스마트 포인터

 : intrusive_ptr은 shared_ptr과 마찬가지로 참조 카운팅 방식으로 객체의 소멸 시점을 결정한다.

 하지만 intrusive_ptr의 경우 관리될 객체가 스스로 자신의 내부에 참조개수를 유지, 관리하도록 요구한다.

 : intrusive_ptr 인스턴스가 새롭게 생성될 때는 intrusive_ptr_add_ref() 함수를 자동으로 호출하여 참조의

개수를 증가시키도록 요구하고, 반대로 intrusive_ptr 인스턴스가 삭제 될 때 intrusive_ptr_release() 함수

를 호출하여, 참조개수가 0일 될 때, 객체를 삭제하도록 요청한다.

( intrusive_ptr_add_ref()와 intrusive_ptr_release() 함수의 경우 사용자가 직접 구현해야 하며, 

 이 때 함수의 인자로 객체의 포인터를 넘겨줍니다. )

: intrusive_ptr은 암묵적 형변환을 허용한다.


  [사용해야 하는 이유]

- 기존의 독자적으로 참조개수를 가지는 객체에 스마트 포인터를 적용하기 위해서 필요

- shared_ptr에 비해 작은 메모리 공간을 차지. (일반 포인터와 마찬가지로 포인터(T*) 형태로 대입 가능!)



[예제]


// intrusivePtrTest.h


#include <iostream>

#include <memory>

#include <vector>

#include <boost/intrusive_ptr.hpp>

#include <boost/shared_ptr.hpp>


using namespace std;


class SharedObject

{

   public:

       SharedObject() : ref_count(0) { cout << "생성됨" << endl; };

       ~SharedObject() { cout << "소멸됨" << endl; };

       void Hello();

       int AddRef();

       int Release();


   private:

       int ref_count;

};


void intrusive_ptr_add_ref(SharedObject* ptr);

void intrusive_ptr_release(SharedObject* ptr); 


// intrusivePtrTest.cpp


#include "intrusivePtrTest.h"


void SharedObject::Hello()

{

    cout << "Hello!" << endl;

}


int SharedObject::AddRef()

{

    // 참조 카운팅 증가시 SharedObject 안에 있는 ref_count 변수를 증가한다.

    return ++ref_count;  // 반환


}


int SharedObject::Release()

{

    // 참조 카운팅 감소시 SharedObject 안에 있는 ref_count 변수를 감소한다.

    if(--ref_count == 0)  // 참조 카운팅이 0 이면       


        delete this;         // 객체 소멸


    return ref_count;     // 참조 카운팅이 0보다 크다면 반환

}  


int main(void)

{

    typedef boost::intrusive_ptr<SharedObject> iPtr;


    iPtr p = new SharedObject();

    vector<iPtr> vec;


    vec.push_back(iPtr(new SharedObject));

    vec.push_back(iPtr(new SharedObject));

    vec.push_back(iPtr(new SharedObject));

    vec.push_back(p);


    p->Hello();

 

    return 0;

}


void intrusive_ptr_add_ref(SharedObject* ptr) // intrusive_ptr이 생성될 경우

{

    ptr->AddRef();

}


void intrusive_ptr_release(SharedObject* ptr) // intrusive_ptr이 소멸될 경우

{

    ptr->Release();

}


 


5. shared_array

 : 동적 배열 포인터를 보관, 유지하는 스마트 포인터 

 : 기능면에서는 shared_ptr과 유사 (배열에 대해 동작)

 : 배열처럼 처리 가능



[예제]


// SharedArrayTest.h


#include <iostream>

#include <memory>

#include <boost/shared_array.hpp>


using std::cout;

using std::endl;


class Sample

{

   public:

       Sample() { cout << "생성" << endl; }

       ~Sample() { cout << "소멸" << endl; }

       void print() { cout << "print" << endl; }

};


// SharedArrayTest.cpp


#include "SharedArrayTest.h"


int main(void)

{

    boost::shared_array<Sample> samplePtr(new Sample[5]); // 동적으로 할당된 배열일 경우 사용


    samplePtr[2].print(); // 배열처럼 사용이 가능하다.


    return 0;


 


6. scoped_ptr 

: 동적으로 할당된 객체의 포인터를 가지며, 유효범위를 벗어나 자신이 삭제 될 때, 

가리키는 객체를 자동으로 삭제하는 스마트 포인터 (가리키는 객체에 대한 삭제를 자동으로 수행)

: auto_ptr과 달리 가지는 포인터를 다른 변수에 복사하거나 할당할 수 없으며, 소유권 역시 이전할 수 없다.

: STL의 컨테이너의 항목으로는 사용할 수 없다는 약점이 있다. → shared_ptr을 사용하는 것이 좋다.

: scoped_array : scoped_ptr과 유사. 동적으로 생성한 객체 배열을 사용할 때 사용!


 

[예제]


// ScopedPtrTest.h


#include <iostream>

#include <memory>

#include <boost/scoped_ptr.hpp>


using std::cout;

using std::endl;


class Sample

{

   public:

       Sample() { cout << "생성" << endl; }

       ~Sample() { cout << "소멸" << endl; }

       void print() { cout << "print" << endl; }

};


// ScopedPtrTest.cpp


#include "ScopedPtrTest.h"


typedef boost::scoped_ptr<Sample> scopePtr;


void printStr(scopePtr* Ptr); // 값 복사가 불가능하므로 포인터 형태로 넘겨야 한다.


int main(void)

{

    scopePtr p1(new Sample());

    scopePtr p2(new Sample());


    p1->print();

    printStr(&p1); // 스마트 포인터 scoped_ptr(scopePtr)의 포인터를 넘긴다.


   /*

       // scoped_ptr - 자신이 가지는 포인터를 다른 인스턴스로 할당하거나 넘겨줄 수 없다.

       //                    한번 가리키는 객체에 대한 삭제의 책임을 전적으로 진다. 

       //                    (복사가 빈번한 STL에서 사용할 수 없다.)


    p2 = p1             // 에러! 할당 불가!

    scopePtr p3(p1) // 에러! 

   */

 

   return 0;

}


void printStr(scopePtr* Ptr) // 값 복사가 불가능하므로 call by reference(address)로 인자를 넘긴다.

{

    (*Ptr)->print();


profile