(Cโบโบ) ๐ชStrong pointer
Smart๊ฐ ์๋๋ผ Strong์ ๋๋ค
#include <stdio.h>
class RefBase
{
int mRefs;
public:
RefBase():mRefs(0){ printf("RefBase::RefBase()\n"); }
virtual ~RefBase(){ printf("RefBase::~RefBase()\n"); }
void incStrong() { mRefs++; }
void decStrong() { if( โmRefs == 0 ) delete this; }
};
template< typename T >
class sp
{
T *mPtr;
public:
sp(T *ptr) : mPtr(ptr) { mPtr->incStrong(); }
sp(const sp<T> &r) : mPtr(r.mPtr) { mPtr->incStrong(); }
~sp() {
mPtr->decStrong();
}
T *operator->() { return mPtr; }
T &operator*() { return *mPtr; }
};
class AAA : public RefBase
{
public:
AAA(){ printf("AAA::AAA()\n"); }
~AAA(){ printf("AAA::~AAA()\n"); }
void foo(){ printf("AAA::foo()\n"); }
};
int main()
{
sp<AAA> p1 = new AAA();
sp<AAA> p2 = p1;
return 0;
}
์๋๋ก์ด๋ ๋ค์ดํฐ๋ธ์์ ์ฌ์ฉํ๋ ์ค์ ์ฝ๋๋ ํจ์ฌ ๋ ๊ธธ๊ณ ๋ณต์กํ์ง๋ง ํต์ฌ๋ง ์ถ๋ฆฌ๋ฉด ์์ ์ฝ๋์ ๊ฐ๋ค. (์ค์ ์ฝ๋๋ ๋ฉํฐ์ฝ์ด ํ๊ฒฝ์ ๊ณ ๋ คํ์ฌ ์ฌ๋ฌ๊ฐ์ง atomic operation๋ ์ฌ์ฉ๋๊ณ ์ํผ ๋ณต์กํ๋ค)
๊ฐ๋
์ ์๋ Smart pointer๊ฐ ์ ๋ช
ํด์ C++ ์ฝ๋๋ฅผ ์ด๋์ ๋ ์ฝ์ ์ ์๋ค๋ฉด ๋์์ ํ์
ํ ์ ์์ ๊ฒ์ด๋ค. ๊ทธ ์ ๋ช
ํ Effective C++์ ์ฒซ ์ฃผ์ ๊ฐ ๋ฐ๋ก RAII(Resource Acquisition Is Initialization)์ธ๋ฐ ํฌ์ธํฐ๋ผ๋ ์์์ ๋ํด์ ๊ทธ๋ ๊ฒ ๊ตฌํํ๋ค๊ณ ๋ณด๋ฉด ๋ ๊ฑฐ๊ฐ๋ค.
์ฃผ๋ชฉํด์ ๋ณผ๋งํ ๋ถ๋ถ์ reference count๋ฅผ sp๊ฐ ๊ฐ์ง๊ณ ์์ง ์๊ณ pointing๋๋ ๊ฐ์ฒด๊ฐ ๊ฐ์ง๊ณ ์๋ค๋ ์ ์ด๋ค. ์๋ฅผ ๋ค์ด SP์์ static member variable์ ๊ฐ์ง๊ณ ์๋ค๋ฉด(๋ง๋ ์๋์ง๋ง) ์ฌ๋ฌ Smart pointer๋ค์ด ์นด์ดํธ๋ฅผ ๊ณต์ ํด๋ฒ๋ฆด ๊ฒ์ด๋ค. ๊ทธ๋์ RefCount๋ฅผ ์์๋ฐ๋ ๊ฐ์ฒด๋ง์ sp๊ฐ ํฌ์ธํ
ํ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ๋ค ์ํด ์ธํฐํ์ด์ค ๋ํ ๋น์ฐํ ์์ํ๋๋ฐ IncrementCount์ DecrementCount๊ฐ์ ๋์๋ค์ด ์ ๊ณต๋๋ค.
#include <stdio.h>
#include "StrongPointer.h"
#include "RefBase.h"
using namespace android;
class AAA : public RefBase
{
public:
AAA(){ printf("AAA::AAA()\n"); }
~AAA(){ printf("AAA::~AAA()\n"); }
void onFirstRef() { printf("onFirstRef()\n"); } // ๋ถ๋ชจ์ ์ธํฐํ์ด์ค๊ฐ virtual ํจ์์ด๋ค
void foo(){ printf("AAA::foo()\n"); }
};
int main()
{
sp<AAA> p1 = new AAA();
sp<AAA> p2 = p1;
return 0;
}
ํ๋ ๋ ์ดํด๋ณผ์ ์ onFirstRef() ํจ์์ด๋ค. ๊ฐ์ํจ์์ด๊ธฐ ๋๋ฌธ์ RefBase๋ฅผ ์์๋ฐ๋๋ค๋ฉด ์๋์ผ๋ก ํธ์ถ๋๋ ๊ฐ์ํจ์์ด๋ค. ์ด ํจ์๋ ์ฒ์์ผ๋ก ์ค๋งํธํฌ์ธํฐ์ ๊ฐ์ด ํ ๋น๋ ๋ ํธ์ถ๋๋๋ฐ, ๊ทธ ์ด์ ๋ ์ข ๊ตฌ๋ฆฐ๊ฑฐ ๊ฐ๋ค.
AAA* p1 = new AAA()
์ ์ ๋ Smart pointer๋ฅผ ์์ฐ๊ณ ๊ฐ์ฒด๋ฅผ ๊ทธ๋ฅ pointer๋ก ์ฌ์ฉํ ์๋ ์๋ ๊ฒ์ด๋ค. ์ด๊ฒ์ ์ปดํ์ผ์๋ฌ ๋ฑ์ผ๋ก ์ ์ดํ ์ ์๋คโฆ(์ ๋ง ์๋? ๊ตฌ๊ธ์ด ๋ชปํ์ผ๋ฉด ๋ชปํ๊ฑด๊ฐ)
๊ทธ๋์ ๊ฐ์ข ๋๋ฐ์ด์ค ๋ฑ ์ค์ํ ๊ฐ์ฒด์์ ์ค์ํ ์ด๊ธฐํ๋ ์์ฑ์๊ฐ ์๋๋ผ onFirstRef()์์ ํ๋๋ก ์ ์ฑ ์ ์ ํ๊ฒ์ด๋ค. Smart pointer๋ฅผ ์์ฐ๋ฉด ์๋๊ฒ๋. ์ข ์ด์ค๋ฝ์ง๋ง ์ด์ฉ๋ง ์ ์ผํ ๋ฐฉ๋ฒ์ผ์ง๋ ๋ชจ๋ฅธ๋ค.
#include <stdio.h>
#include "StrongPointer.h"
#include "RefBase.h"
using namespace android;
class AAA;
class BBB;
class AAA : public RefBase
{
public:
sp<BBB> pb;
AAA(){ printf("AAA::AAA()\n"); }
~AAA(){ printf("AAA::~AAA()\n"); }
void foo(){ printf("AAA::foo()\n"); }
};
class BBB : public RefBase
{
public:
sp<AAA> pa;
BBB(){ printf("BBB::BBB()\n"); }
~BBB(){ printf("BBB::~BBB()\n"); }
void foo(){ printf("AAA::foo()\n"); }
};
int main()
{
{
sp<AAA> p1 = new AAA();
sp<BBB> p2 = new BBB();
p1->pb = p2;
p2->pa = p1;
}
printf("step 1.\n");
return 0;
}
์ด๋ฒ์ sp์ ์ํธ์ฐธ์กฐ ๋ฌธ์ ์ด๋ค.
์ ์์ ์ฒ๋ผ ๋ฉค๋ฒ์ธ Smart pointer๊ฐ ์๋ก๋ฅผ ์ฐธ์กฐํ ๊ฒฝ์ฐ ์ ์๊ฐํด๋ณด๋ฉด, ๋ฉค๋ฒ์ ์ฐธ์กฐ๋ฅผ ํตํด์ ๊ฐ์ฒด์ RefCount๊ฐ 2๊ฐ ๋๋ฏ๋ก sp๊ฐ Scope์์ ๋๊ฐ์ ์๋ฉธ๋๋๋ผ๋ RefCount๋ 1์ด ๋๊ณ ๊ฐ์ฒด๋ ์๋ฉธ๋์ง ์๋๋ค. ์ด๊ฒ์ sp ๋ฟ๋ง ์๋๋ผ Smart pointer๋ฅ๊ฐ ๊ณตํต์ ์ผ๋ก ๊ฐ์ง๋ ๋ฌธ์ ์ด๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ๋ค์์ ์๊ฐํ wp ์ฆ, Weak pointer๊ฐ ๋์
๋๋ค.