Modern C++

[C++] SmartPointer - unique_ptr

태현123 2021. 7. 10. 21:50
728x90
반응형
SMALL

오늘 다뤄볼 내용은 SmartPointer이다.

 

일단 개념에 대해 알아보면,

-  a smart pointer is an abstract data type that simulates a pointer while providing added features, such as automatic memory management or bounds checking. Such features are intended to reduce bugs caused by the misuse of pointers, while retaining efficiency. Smart pointers typically keep track of the memory they point to, and may also be used to manage other resources, such as network connections and file handles. Smart pointers were first popularized in the programming language C++ during the first half of the 1990s as rebuttal to criticisms of C++'s lack of automatic garbage collection.[1][2]

 

Smart pointer - Wikipedia

In computer science, a smart pointer is an abstract data type that simulates a pointer while providing added features, such as automatic memory management or bounds checking. Such features are intended to reduce bugs caused by the misuse of pointers, while

en.wikipedia.org

[출처 : 위키백과]

스마트 포인터란 자동적으로 메모리를 관리해주거나, 범위검사를 도와주는 포인터이다.

 

우리가 C++을 사용하면서 포인터에 대하여 동적할당을 new로 할 경우, delete로 소멸을 시켜주지 않으면, Memory Leak 현상 또는 소멸된 객체를 두번 소멸 시켜버리는 double free현상이 발생한다. 근데 코드가 길어지고 복잡해지게 되면 이런 포인터들의 관리가 어려워진다. 

Java나 C#에서는 Garbage Collector라는 기능이 있어 포인터에 대한 신경을 많이 쓰지 않아도 되지만, C++의 경우엔 그렇지 않다.

그렇기 때문에 Modern C++에서는 Smart Pointer라는 개념을 도입했다. 이 스마트포인터를 사용하면, 사용이 끝난 메모리에 대하여 자동으로 해제시켜준다는 큰 장점이 있다.

 

스마트포인터의 종류

- unique_ptr

- shared_ptr

- weak_ptr

 

그 중 오늘 알아볼 것은 unique_ptr이다.

 

unique_ptr<class>

-> 하나의 스마트 포인터만이 특정 객체를 소유한다. 그렇기 때문에, 원시 포인터는 공유할 수 없다. 이에 따라 복사, 대입이 불가능하다. unique_ptr가 범위를 벗어날 때, 원시 포인터는 삭제된다. 하지만, unique_ptr의 소유권을 다른 unique_ptr에게 이동시킬 수는 있다.

 

- 활용법?

>>

클래스의 멤버변수 : 소멸자가 호출되면, 스스로 해제
vector<unique_ptr<class>> : vector를 .clear()하면, 자동적으로 포인터를 해제시켜줌.

unique_ptr의 특징<복사 불가>

다음 사진과 같이 unique_ptr<int>인 ptr1을 복사하게 되면, 에러가 발생한다.

 

c++11에서 원시포인터를 공유할 수 있는 경우가 있었는데, 이럴 때는 unique_ptr의 개념이 깨지게 되는 불상사가 생길 수 있었는데, 이를 보완하기 위하여 c++ 14에서 make_unique라는 키워드가 추가되어 원시 포인터의 공유를 막을 수 있게 되었다.

 

그래서 최근에는 다음과 같이 사용한다.

unique_ptr의 사용

그런데 아까 말했듯이, unique_ptr의 경우 포인터의 소유권을 이동시킬 수 있다고 했다. 다음 코드를 보자.

i_ptr을 make_unique를 이용하여 선언을 하였다. 이후, i_ptr에서 move하여 i_ptr의 소유권을 i_ptr2가 받게 되었다.

이 move라는 함수는 LValue를 RValue로 바꾸어주는 함수이다.  즉, i_ptr은 임시 값이 되어 move함수가 호출 된 이후로는 사용할 수 없다.

 

L Value와 R Value?

- L Value의 경우 단일 표현식 이후에도 없어지지 않고 지속되는 타입이다.(변수, 포인터 ...)

- R Value의 경우 표현식이 종료된 이후에는 더이상 존재하지 않는 타입이다.(임시 값)

 

그렇다면, 다음 코드를 실행했을 때 어떤 결과가 발생할까?

답은, i_ptr이 nullptr이기 때문에, 컴파일 오류가 발생한다. 다음 코드를 에러가 나지 않게 하려면, nullptr일 경우 출력하지 않도록 하면 에러가 발생하지 않고 정상적으로 작동할 것이다.

코드 실행결과, i_ptr2의 참조값 5를 리턴

이 이동마저 불가능하게 하는 키워드가 있다. 바로, const이다. const unique_ptr의 경우 소유권 이전을 할 수 없다.

 

이 밖의 unique_ptr의 관련 함수를 살펴보면, 다음과 같은 것들이 있다.

- reset()

reset 함수

다음과 같이 reset함수를 실행하게 되면, i_ptr2를 nullptr로 만들어 버린다. 현재 코드에서는 nullptr을 참조했으므로, 컴파일 오류가 발생한다.

 

- get()

get 함수

unique_ptr의 get함수는 말 그대로 현재 unique_ptr이 참조하고 있는 포인터값을 반환해주는 함수이다. 따라서, 다음 코드를 실행하면, i_ptr2을 a가 반환받아 i_ptr2의 참조값인 5를 출력한다.

 

 

- release()

release 함수

release함수는 현재 unique_ptr을 반환해주고, unique_ptr을 nullptr로 만들어버린다. 즉, release를 하고 난 이후 반환된 포인터는 unique_ptr이 더 이상 아니다.

>> ?? 왜 unique_ptr이 아니지?

아닌 이유

위에서 말했다시피, unique_ptr은 복사, 대입이 안된다고 말했다. 그러니 만약 release함수를 호출하고 받아낸 p가 unique_ptr이라면, int*k = p에서 빨간줄이 그어져야한다. 근데, 그런 일이 없다. 

-> 이 부분은 제추측입니다. 아니라면 댓글로 알려주시면 감사드리겠습니당..

 

여기까지 스마트포인터 중 하나인 unique_ptr에 대하여 알아보았다. 정리하면서 공부에 많은 도움이 된 것같다.

 

>>>> 공부하는 입장에서 지적해주시면 감사하게 받겠습니다!

반응형
LIST

'Modern C++' 카테고리의 다른 글

[C++] Container - List  (0) 2021.07.19
[C++] Container - array, vector  (0) 2021.07.18
[C++] SmartPointer - weak_ptr  (0) 2021.07.16
[C++] SmartPointer - shared_ptr  (0) 2021.07.11
C++ 11 복습 계획  (0) 2021.07.04