이이프
IeF 제멋대로 세상
이이프
전체 방문자
오늘
어제

공지사항

  • ✔ Info
  • 전체 글보기 (56)
    • 💻프로그래밍 내용 정리 (55)
      • C (0)
      • C++17 (55)
    • 💻게임메이커 (0)
    • 💻언리얼엔진 (0)
    • 💻유니티 (0)
    • 🎈[팀&자작]게임소개 (0)
    • 📃게임제작기술 (0)
    • 🎨그림놀이 (0)
    • 📒대학생활 (0)
    • 😃잡담 (1)
    • 🕹게임성과 (0)
    • 💷자격증 (0)

블로그 메뉴

  • 방명록

최근 글

최근 댓글

티스토리

hELLO · Designed By 정상우.
이이프
💻프로그래밍 내용 정리/C++17

[C++ 7.4.1] unique_ptr

💻프로그래밍 내용 정리/C++17

[C++ 7.4.1] unique_ptr

2022. 9. 25. 11:56
728x90

1. unique_ptr 생성 방법

다음은 Simple 객체를 힙에 할당한 뒤 이를 해제하지 않아 메모리 누수가 현상이 발생하는 경우이다.

void leaky()
{
    Simple* mySimplePtr = new Simple();
    mySimplePtr->go();
}

 

코드를 작성할 때 동적으로 할당한 메모리를 제대로 해제한다고 여기기 쉽다.

하지만 그렇지 않을 가능성이 훨씬 높다. 다음 함수를 보자.

void couldBeLeaky()
{
    Simple* mySimplePtr = new Simple();
    mySimplePtr->go();
    delete mySimplePtr;
}

이 함수는 Simple 객체를 동적으로 할당해서 사용하고 나서 delete를 호출한다.

이렇게 해도 메모리 누수가 발생할 가능성은 남아 있다.

go() 메서드에 익셉션(에러)이 발생하면 delete가 실행되지 않기 때문이다.

 

unique_ptr 구현

앞에서 본 두 코드 모두 unique_ptr로 구현해야 한다.

그러면 객체에 대해 delete를 직접 호출하지 않아도 된다.

unique_ptr 인스턴스가 스코프를 벗어나면 소멸자가 호출될 때 Simple 객체가 자동으로 해제된다.

void notLeaky()
{
    auto mySimpleSmartPtr = make_unique<Simple>();
    mySimpleSmartPtr->go();
}

이 코드는 C++14부터 제공하는 make_unique()와 auto 키워드를 동시에 적용했다.

그래서 Simple이라는 포인터 타입만 지정했다.

Simple 생성자에서 매개변수를 받는다면 make_unique() 호출문의 소괄호 사이에 지정하면 된다.

예를 들어 Simple(int, int)라면 make_unique<Simple>(1, 2);와 같이 생성자 인수를 전달할 수 있다.

 

make_unique()를 지원하지 않는 컴파일러를 사용한다면 다음과 같이 unique_ptr로 생성한다.

unique_ptr<Simple> mySimpleSmartPtr(new Simple());

C++ 이전에는 타입을 단 한 번만 지정하기 위해서 뿐만 아니라 안전을 위해 반드시 make_unique()를 사용해야 했다.

 

 


 

2. unique_ptr 사용 방법

스마트 포인터는 일반 포인터와 똑같이 *나 ->로 역참조 한다.

예를 들어 앞에서 본 예제에서 go() 메서드를 호출할 때 -> 연산자를 사용했다.

mySimpleSmartPtr->go();

 

다음과 같이 일반 포인터처럼 작성해도 된다.

(*mySimpleSmartPtr).go();

 

get() 메서드를 이용하면 내부 포인터에 직접 접근할 수 있다.

일반 포인터만 전달할 수 있는 함수에 스마트 포인터를 전달할 때 유용하다. 예를 들어 다음과 같은 함수가 있다고 하자.

void processData(Simple* simple) { /* 스마트 포인터를 사용하는 코드 */ }

그러면 이 함수를 다음과 같이 호출할 수 있다.

    auto mySimpleSmartPtr = make_unique<Simple>();
    processData(mySimpleSmartPtr.get());

 

reset()을 사용하면 unique_ptr의 내부 포인터를 해제하고, 필요하다면 이를 다른 포인터로 변경할 수 있다.

예를 들면 다음과 같다.

    mySimpleSmartPtr.reset();             // 리소스 해제 후 nullptr로 초기화
    mySimpleSmartPtr.reset(new Simple()); // 리소스 해제 후 새로운 Simple 인스턴스로 설정

 

release() 를 이용하면 unique_ptr와 내부 포인터의 관계를 끊을 수 있다.

release() 메서드는 리소시에 대한 내부 포인터를 리턴한 뒤 스마트 포인터를 nullptr로 설정한다.

그러면 스마트 포인터는 그 리소스에 대한 소유권을 잃으며, 리소스를 다 쓴 뒤 반드시 직접 해제해야 한다.

예를 들면 다음과 같다.

    Simple* simple = mySimpleSmartPtr.release(); // 소유권을 해제한다.
    // simple 포인터를 사용하는 코드
    delete simple;
    simple = nullptr;

unique_ptr은 단독 소유권을 표현하기 때문에 복사할 수 없다.

std::move() 유틸리티를 사용하면 하나의 unique_ptr를 다른 곳으로 이동할 수 있는데,

복사라기보다는 이동의 개념이다.

 

 


 

3. unique_ptr와 C 스타일 배열

unique_ptr 은 기존 C 스타일의 동적 할당 배열을 저장하는 데 적합하다.

예를 들어 정수 10개를 가진 C 스타일의 동적 할당 배열을 다음과 같이 표현할 수 있다.

    auto myVariableSizedArray = make_unique<int[]>(10);

이렇게 unique_ptr로 C 스타일의 동적 할당 배열을 저장할 수 있지만,

이보다는 std::array나 std::vector와 같은 표준 라이브러리 컨테이너를 사용하는 것이 좋다.

 

 


 

4. 커스텀 제거자

기본적으로 unique_ptr은 new와 delete로 메모리를 할당하거나 해제한다.

하지만 다음과 같이 방식을 변경할 수 있다.

int* malloc_int(int value)
{
    int* p = (int*)malloc(sizeof(int));
    *p = value;
    return p;
}

int main()
{
    unique_ptr<int, decltype(free)*>myIntSmartPtr(malloc_int(42), free);
    return 0;
}

이 코드는 malloc_int()로 정수에 대한 메모리를 할당한다.

unique_ptr은 메모리를 표준 free() 함수로 해제한다.

'💻프로그래밍 내용 정리 > C++17' 카테고리의 다른 글

[C++ 7.4.3] weak_ptr  (0) 2022.10.03
[C++ 7.4.2] shared_ptr  (0) 2022.09.25
[C++ 7.3.4] 객체 풀  (0) 2022.08.24
[C++ 7.3.3] 가비지 컬렉션  (0) 2022.08.24
[C++ 7.3.2] 커스텀 메모리 관리  (0) 2022.08.24
  • 1. unique_ptr 생성 방법
  • 2. unique_ptr 사용 방법
  • 3. unique_ptr와 C 스타일 배열
  • 4. 커스텀 제거자
'💻프로그래밍 내용 정리/C++17' 카테고리의 다른 글
  • [C++ 7.4.3] weak_ptr
  • [C++ 7.4.2] shared_ptr
  • [C++ 7.3.4] 객체 풀
  • [C++ 7.3.3] 가비지 컬렉션
이이프
이이프
게임 프로그래머 지망생 / Since 2022.08.14

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.