본문 바로가기

카테고리 없음

[C++] 스마트 포인터 -1 (Smart Pointer)

Smart Pointer


스마트 포인터란 ?


인스턴스를 동적으로 할당한 후에 예기치 못한 상황으로 프로그램이 종료되거나,

코드 작성시에 메모리를 할당한 후 메모리 해제를 하지 않았을 때 생기는 메모리 누수현상(memory leak)을 방지하고자 태어난 새로운 표준 문법입니다.

간단하게 얘기하자면 동적 할당한 인스턴스를 '자동'으로 해제시켜주는 유용한 포인터입니다.

스마트 포인터의 종류는 자주쓰이는 3가지가 있고 그외에 것도 있지만 자주안쓰입니다.


스마트 포인터의 종류


auto_ptr : 동적 할당한 인스턴스를 가르키며 소멸자로 인스턴스를 자동 해제시켜줍니다. 가장 오래된 스마트 포인터이며 여러문제로 쓰이지않습니다.

shared_ptr : 동적 할당한 인스턴스를 가르키지만, 가르키는 인스턴스 입장에서 포인팅된 횟수까지 계산합니다. 포인팅이 0이라면 대상을 삭제합니다.

unique_ptr : shared_ptr끼리는 같은 인스턴스를 여러포인터가 포인팅할 수 있지만 unique_ptr은 오직 한 인스턴스당 한 포인터만 포인팅 가능합니다. 

weak_ptr : shared_ptr가 포인팅하는 인스턴스에 접근할 수 있게 하지만, 참조 수로 계산하지 않습니다.



위에서 적어놨듯이 auto_ptr은 사용하지 말라고 권장되어지는 포인터입니다.

사용조건에 부합하다면 사용해도 되겠지만.. 예외가 너무많고 오류도 너무많습니다.

치명적인 오류도 발생하게 되고 코딩에 굉장히 불편함을 줘요.




auto_ptr의 문제점


결과부터 말하자면 배열로 할당한 인스턴스를 배열로 삭제시키지 않는 문제점,포인터끼리의 복사연산시 '복사'가 아닌 '이동'이 되버린다는 점입니다.


아래는 auto_ptr의 사용 예입니다. 제대로 컴파일됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
#include <memory>        //스마트포인터
#include <iostream>
#include <string>
using namespace std;
 
int _tmain(int argc,_TCHAR* argv[])
{
     //string형을 가르키는 스마트포인터 sptr을 선언하고
    //string형을 할당한후 그것을 가르킨다.
    auto_ptr<string> sptr(new string); 
    return 0;
}
cs



이것은 컴파일 오류가 뜨는 예입니다. 포인터가 가르키는 인스턴스가 배열형식이면, 배열형식으로 삭제하지 않아 오류가 발생합니다.
1
2
3
4
5
6
7
8
9
10
11
12
#include <memory>        //스마트포인터
#include <iostream>
#include <string>
using namespace std;
 
int _tmain(int argc,_TCHAR* argv[])
{
     //string형을 가르키는 스마트포인터 sptr을 선언하고
    //string[3]형을 할당한후 그것을 가르킨다.
    auto_ptr<string> sptr(new string[3]); 
    return 0;
}
cs

얕은복사의  문제점입니다. 코드와 코드의 실제 작동을 표현한 사진을 보세여.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <memory>        //스마트포인터
#include <iostream>
#include <string>
using namespace std;
 
int _tmain(int argc,_TCHAR* argv[])
{    
    //auto_ptr형 sptr1,sptr2선언  sptr1초기화
    auto_ptr<string> sptr1(new string);
    auto_ptr<string> sptr2;
    //sptr2에 sptr1정보 복사    
    sptr2 = sptr1;
    return 0;
}
cs


실제로 바라던 복사는 'sptr1이 가르키는 인스턴스를 새로 하나 더 할당해서 sptr2이 가르키도록' 하는것이였지만

실제로는 sptr1의 객체를 sptr2이 뺏어가버리는 꼴이 되버리고 맙니다....(-_-)

그리고 본인은 NULL값이 되버리는 이상한 상황..

결론은 쓰지말자 입니다..T^T


쓰지말라고 하면되지 왜 문제점을 설명했느냐.. 그이유는 shared_ptr과 unique_ptr이 저런 문제점을 해결하고자 탄생했기 때문이죠!


<ps.사실 스마트포인터는 클래스로 구현되있답니다.. 'ㅅ'>