๐Ÿ“– C๋ž‘ C++

C++ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์•Œ์•„๋ณด์ž - (1) unique_ptr

bell22 2021. 5. 25. 02:15

C++์—๋Š” ์•„์ฃผ ์œ ์šฉํ•œ ๊ฐœ๋…์ด ์žˆ๋‹ค

๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ํ•  ๋•Œ๋งˆ๋‹ค ๊ณ ๋ คํ•ด์•ผํ•  ์ ์€ ๋ฐ”๋กœ "๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜"์ธ๋ฐ,

๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์กฐ๊ธˆ์€ ์ž์œ ๋กญ๊ฒŒ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ผ๋Š” ๊ฒƒ์ด๋‹ค

 

๊ฐ€์žฅ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š”๊ฑด shared_ptr์ด์—ˆ๋Š”๋ฐ,

์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ์žˆ๋Š”๊ฑด ์ด์œ ๊ฐ€ ์žˆ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด์„œ

ํ•˜๋‚˜์”ฉ ์ •๋ฆฌํ•˜๋ ค๊ณ  ํ•œ๋‹ค

(๋ชจ๋˜ C++ ์ž…๋ฌธ ๊ต์žฌ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ฅ)

 


1. ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์—๋Š” ๋ญ๊ฐ€ ์žˆ์ง€?

์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” 3๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค

 

1) unique_ptr (์˜ค๋Š˜ํ• ๊ฑฐ)

2) shared_ptr

3) weak_ptr

 

์š”๋ ‡๊ฒŒ 3๊ฐ€์ง€ ์ธ๋ฐ, ์ฐธ๊ณ ๋กœ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” C++ 11์—์„œ ๋„์ž…๋œ ๊ฐœ๋…์ด๋‹ค

C++ 03์—๋Š” auto_ptr๋ผ๋Š” ๊ฒƒ๋„ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค -_-a ํ•˜์ง€๋งŒ ์‚ญ์ œ๋จ ์“ฐ์ง€๋งˆ์…ˆ

 

1-1) ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ํ—ค๋”๋Š”?

 

#include <memory>
or
#include "boost/shared_ptr.hpp"

 

๊ธฐ๋ณธ STL์—์„œ ์ œ๊ณตํ•˜๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋Š” <memory> ํ—ค๋”์—์„œ ์“ธ ์ˆ˜ ์žˆ๋‹ค

๊ทผ๋ฐ C++11์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ธ๋ฐ, C++ 11์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ์ˆ˜๋„ ์žˆ๋‹ค...

๊ทธ๋Ÿด ๋•Œ๋Š” Boost์— ์žˆ๋Š”๊ฑธ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค๊ณ  ํ•œ๋‹ค

 

1-2) ๊ทธ๋ƒฅ ํฌ์ธํ„ฐ๋ฅผ ์“ฐ๋ฉด ์•ˆ๋˜๋Š”๊ฑด๊ฐ€?

์จ๋„ ๋œ๋‹ค ใ…‹

์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉ์‹œ์— ํฐ ์žฅ์ ์€ ์‚ฌ์šฉํ•˜๋Š” ํฌ์ธํ„ฐ๊ฐ€ ๋งŒ๋ฃŒ๋˜๋ฉด

๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ž๋™์œผ๋กœ ํ•ด์ œ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ์ฐจ์›์—์„œ ํŽธํ•˜๋‹ค

 

ํ•˜์ง€๋งŒ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ๋Š” ์กฐ๊ธˆ ๊นŒ๋‹ค๋กญ๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ

์ž˜ ์•Œ๊ณ  ์‚ฌ์šฉํ•˜์ž ใ…‹

 

2. unique_ptr

์ด๋ฆ„์—์„œ ๋Š๊ปด์ง€๋Š”๊ฐ€... ๋ญ”๊ฐ€ ์œ ๋‹ˆํฌํ•˜๋‹ค

์œ ๋‹ˆํฌํ•  ๊ฒƒ ๊ฐ™์€ ๋Š๋‚Œ์ด ๋“ ๋‹ค..

 

unique_ptr์€ ํฌ์ธํ„ฐ๋ฅผ ํ†ตํ•ด Uniqueํ•œ ์†Œ์œ ๊ถŒ์„ ๊ฐ€์ง€๊ณ 

unique_ptr ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ ํ•ด๋‹น ๊ฐœ์ฒด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์ด๋‹ค

 

๋ฐ”๋กœ ์‚ฌ์šฉ ์˜ˆ์‹œ๋ฅผ ๋ณด๊ฒ ๋‹ค

 

#include <memory>
#include <iostream>

using namespace std;

int main(void)
{
    std::unique_ptr <int> ptr(new int(10));

    cout << *ptr << endl;

    return 0;
}

 

๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ์— ๋Œ€ํ•ด์„œ๋Š” new๋กœ ์ƒ์„ฑ ํ•ด์คฌ๊ณ ,

ํฌ์ธํ„ฐ์ด๊ธฐ ๋•Œ๋ฌธ์— *ptr๋กœ ๊ฐ’์„ ์ถœ๋ ฅ์„ ํ•ด์ค€ ์˜ˆ์ œ์ด๋‹ค

 

ํ•ด๋‹น ํฌ์ธํ„ฐ๋Š” ๋งŒ๋ฃŒ๋˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ž๋™์œผ๋กœ ํ•ด์ œ๋  ๊ฒƒ์ด๋‹ค

๋ฉ”๋ชจ๋ฆฌ๋Š” ์ž๋™์œผ๋กœ ํ•ด์ œ๋˜์ง€๋งŒ, ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋™์ ์œผ๋กœ ํ• ๋‹นํ•ด์ฃผ์ง€ ์•Š์•˜๋‹ค๋ฉด

core๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค

 

2-1) unique_ptr์ด uniqueํ•œ ์ด์œ 

unique_ptr์€ ์œ ๋‹ˆํฌ!!! ๊ณ ์œ ํ•œ!!! ํฌ์ธํ„ฐ๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ–๊ณ  ์žˆ๋Š” ์ด์œ ๊ฐ€ ์žˆ๋‹ค..

์™œ๋ƒ๋ฉด, ๋‹ค๋ฅธ ํฌ์ธํ„ฐ ํƒ€์ž…์— ํ• ๋‹น๋˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค

 

๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ๋ฐ”๊พผ๋‹ค๊ณ  ํ•œ๋‹ค๊ฑฐ๋‚˜,

๋‹ค๋ฅธ unique_ptr ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•œ๋‹ค!? ํ•˜๋ฉด

์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋œฐ ๊ฒƒ์ด๋‹ค

 

"error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]"

 

ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฅดํ‚ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๊ณ  ์‹ถ๋‹ค๋ฉด get()์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค

๋ฐ”๋กœ ์š”๋ ‡๊ฒœ

 

#include <memory>
#include <iostream>

using namespace std;

int main(void)
{
    std::unique_ptr <int> ptr(new int(10));
    cout << *ptr << endl;

    int* raw_ptr = ptr.get();
    cout << *ptr << endl;

    return 0;
}

 

unique_ptr์€ ๋‹ค๋ฅธ unique_ptr์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ๋„ ์•ˆ๋œ๋‹ค

 

int main(void)
{
    std::unique_ptr <int> ptr(new int(10));
    cout << *ptr << endl;
	
    /* ์—๋Ÿฌ ๋ฐœ์ƒ */
    std::unique_ptr <int> ptr_cp{ptr};
    cout << *ptr_cp << endl;

    return 0;
}

 

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋‚  ๊ฒƒ์ด๋‹ค ใ…‹

unique_ptr์€ ์ด๋™๋งŒ ํ•  ์ˆ˜ ์žˆ๋‹ค

์ด๋™์€ ๋ฌด์Šจ ํ•จ์ˆ˜๋ƒ... move() ๋‹ค

 

std::unique_ptr <int> ptr_cp{move(ptr)};

 

๋ฐ”๋กœ ์ด๋ ‡๊ฒŒ ใ…‹

move() ๋ถˆํ•„์š”ํ•œ ๋ณต์‚ฌ๋ฅผ ํ”ผํ•˜๋ ค๊ณ  ํŠธ๋ฆญ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ๋ฒ•์ธ๋ฐ

 

๊ทธ๋ฆผ์„ ๋นŒ๋ ค ์„ค๋ช…ํ•˜์ž๋ฉด

ptrA์— Song ๊ฐ์ฒด์˜ ์†Œ์œ ๊ถŒ์ด ๋ถ€์—ฌ๋˜๊ณ ,

move๋ฅผ ํ•˜๋ฉด ๊ทธ ์†Œ์œ ๊ถŒ์„ ๊ทธ๋Œ€๋กœ ptrB์— ๋„˜๊ฒจ์ฃผ๊ฒŒ ๋œ๋‹ค

ptrA๋Š” nullptr์ด ๋œ๋‹คใ…‹

 

์ •๋ฆฌํ•˜์ž๋ฉด unique_ptr์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์ œํ•˜๋Š” ๋ณต์‚ฌ(copy)๋Š” ์•ˆ๋ผ์š”

์›๋ž˜ ์ฃผ์†Œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ์ด๋™(move)์€ ๋ผ์š”

→ ๊ณ ์œ ํ•œ ์†Œ์œ ๊ถŒ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค

 

2-2) unique_ptr์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ new๋ฟ์ธ๊ฐ€?

์•„๋‹ˆ๋‹คใ…‹

๋ฌผ๋ก  ์ด๋ ‡๊ฒŒ๋„ ๋งŽ์ด ์“ฐ๋Š”๋ฐ, C++ 14 ๋ถ€ํ„ฐ ์ œ๊ณตํ•˜๋Š” make_unique()๋ฅผ ์“ฐ๋ฉด

๋” ์•ˆ์ „ํ•˜๊ณ  ์ฝ”๋“œ์— ํ†ต์ผ์„ฑ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค

 

int main(void)
{
    std::unique_ptr <int> ptr = make_unique<int>(10);
    cout << *ptr << endl;

    return 0;
}

๋ฐ”๋กœ ์ด๋ ‡๊ฒŒใ…‹ 

new๋กœ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์Šต๊ด€์ด ๋˜์—ˆ๋Š”๋ฐ, make ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ด์•ผ๊ฒ ๋‹น

 

2-3) unique_ptr์„ return ๋ฐ›์œผ๋ฉด ์†Œ์œ ๊ถŒ์€?

ํฌ๊ฒŒ ์ƒ๊ฐ์•ˆํ•ด๋„ ๋œ๋‹ค

์˜ˆ์‹œ๋กœ ๋ฐ”๋กœ ๊ธ”๊ธ”

std::unique_ptr<int>
unique_func()
{
    return std::unique_ptr<int>{new int(10.0)};
}

int main(void)
{
    auto ptr = unique_func();
    cout << *ptr << endl;

    return 0;
}

 

์š”๋ ‡๊ฒŒ ๋˜๋ฉด unique_ptr์„ ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ํ•  ๋•Œ

๋ฉ”๋ชจ๋ฆฌ์˜ ์†Œ์œ ๊ถŒ์„ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด ๊ฒฝ์šฐ์—๋Š” move๋ฅผ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค

 

2-4) ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์ง€์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด?

์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ์—๋Š”

์•Œ์•„์„œ delete๊ฐ€ ๋œ๋‹ค๊ณ  ์•Œ๊ณ  ์žˆ์ง€๋งŒ... ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ๋‚ด๊ฐ€ ์ง€์šฐ๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์ง€ ์•Š์€๊ฐ

๊ทธ๋Ÿด๋•Œ๋Š” reset()์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค

 

int main(void)
{
    std::unique_ptr <int> ptr(new int(10));
    cout << *ptr << endl;

    std::unique_ptr <int> ptr_cp{move(ptr)};
    cout << *ptr_cp << endl;

    ptr_cp.reset();
    if( !ptr_cp )
        cout << "nullptr" << endl;
    else
        cout << *ptr_cp << endl;

    return 0;
}

 

์š”๋ ‡๊ฒŒ ํ•˜๋ฉด nullptr์ด๋ผ๋Š” ๋ฌธ์ž์—ด์ด ์ถœ๋ ฅ๋œ๋‹ค

ptr_cp์—๋Š” ptr์˜ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ moveํ•˜์—ฌ ๊ฐ–๊ณ  ์žˆ๋Š”๋ฐ,

ptr_cp์— ๋Œ€ํ•ด์„œ reset()์„ ํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์‚ญ์ œํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค

 


 

๋‚ด์ผ์€ shared_ptr ๊ณต๋ถ€ํ• ๋ž˜