Home [C++] 스마트 포인터 - unique_ptr
Post
Cancel

[C++] 스마트 포인터 - unique_ptr

description

unique_ptr은 이름에서 알 수 있듯이 하나의 대상에 하나의 unique_ptr 포인터로만 가리킬 수 있습니다.

auto_ptr과 비슷해 보이지만 auto_ptr과 다르게 컴파일 에러를 발생시켜 하나의 대상에 여러 개의 포인터가 가리키는 일을 컴파일 단계에서 차단해 줍니다.

사용 방법은 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<iostream>
#include<memory>

using namespace std;

class TEST
{
public:
    TEST()
    {
        cout << "생성자 호출" << endl;
    }

    ~TEST()
    {
        cout << "소멸자 호출" << endl;
    }

    void Print()
    {
        cout << "Print" << endl;
    }
};

int main()
{
    unique_ptr<TEST> up(new TEST());
}

// 출력 결과
생성자 호출
소멸자 호출

위에서 설명했듯이, 하나의 대상에 하나의 unique_ptr 포인터로만 가리킬 수 있기 때문에

다른 unique_ptr 포인터로 가리키게 된다면 컴파일 에러가 발생하는 것을 볼 수 있습니다.

1
2
3
4
5
6
7
int main()
{
    unique_ptr<TEST> up(new TEST());
    unique_ptr<TEST> up2(up); // Compile Error!!!!
    unique_ptr<TEST> up3;
    up3 = up; // Compile Error!!!!
}

cpp-14

컴파일 에러가 발생하는 이유는

unique_ptr 정의부를 가보면 “복사 생성자”와 “대입 연산자”에 대해 delete 처리를 했기 때문입니다.( == 삭제된 함수)

cpp-15


소유권 이전하기

만약 소유권을 이전해야 한다면 어떻게 해야 할까요??

unique_ptr은 “복사 생성자”와 “대입 연산자”가 delete 처리되어 삭제된 함수로 취급하고 있습니다.

그렇기 때문에 복사 생성자와 대입 연산자로 소유권을 이전할 수 없는데요.

대신 “이동 생성자”와 “이동 대입 연산자”를 지원하고 있습니다.

그렇기 때문에 std::move를 통해 소유권을 이전할 수 있습니다.

여담으로

“이동 생성자”와 “이동 대입 연산자”로 소유권을 이전하는 것은

unique_ptr이 소유권을 이전할 때 왜 원본 데이터가 NULL이 되는지에 대한 증명으로도 볼 수 있습니다.

“이동 생성자”를 통해 객체를 생성하면
원본 객체의 자원을 얕은 복사로 가져오면서 원본 객체는 NULL 처리하기 때문입니다.

std::move는 특정 객체가 이동될 수 있음을 알려주는 함수입니다.
여기서 “이동”이란, 특정 객체가 가지고 있는 자원을 효율적으로 전달할 수 있음을 뜻합니다.

정리하면, std::move는 자원을 다른 객체로 효율적으로 전달할 수 있음을 알려주는 함수입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<iostream>
#include<memory>

using namespace std;

class TEST
{
    int num = 0;
public:
    TEST(int p_num):num(p_num)
    {
        cout << "생성자 호출" << endl;
    }

    ~TEST()
    {
        cout << "소멸자 호출" << endl;
    }

    void Print()
    {
        cout << num << endl;
    }
};

int main()
{
    unique_ptr<TEST> up(new TEST(10));
    unique_ptr<TEST> up2;
    up2 = move(up);

    up2->Print();

    if (!up)
        cout << "up is null" << endl;
}

// 출력 결과
생성자 호출
10
up is null
소멸자 호출

소유권 이전된 unique_ptr 포인터는 댕글링 포인터가 됩니다.

그러므로 댕글링 포인터가 된 unique_ptr 포인터를 가지고 값을 참조하려고 하면 런타임 에러가 발생하니 주의해야 합니다.


방법: unique_ptr 인스턴스 만들기 및 사용

std::move - cppreference.com

This post is licensed under CC BY 4.0 by the author.

[C++] 스마트 포인터 - shared_ptr

[Unity Shader] ShaderLab과 Shader 작성 방식