(Cโบโบ) ๐Ÿ’ชStrong pointer

Smart๊ฐ€ ์•„๋‹ˆ๋ผ Strong์ž…๋‹ˆ๋‹ค

2 minute read

#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๊ฐ€ ๋„์ž…๋œ๋‹ค.