๐Ÿ“– C๋ž‘ C++

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

bell22 2021. 6. 25. 17:43

์˜ค๋Š˜์€ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ ์ค‘...

๋‘ ๋ฒˆ์งธ์ธ shared_ptr์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณผ๊ฑฐ๋‹ค

 

์š”์ฆ˜ ๋„ค์ด๋ฒ„ ๋ธ”์ฑŒ ์ด๋ฒคํŠธ๋ฅผ ํ•˜๊ณ  ์žˆ๋Š”๋ฐ

๊ฐ€์šด๋ฐ ์ •๋ ฌ๋กœ ํ•˜๋‹ˆ๊นŒ ์‚ฌ์ง„ ์ฒจ๋ถ€ํ•˜๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ์ข‹์•˜์–ด์„œ

์™ผ์ชฝ์ •๋ ฌํŒŒ์˜€๋Š”๋ฐ ๋ฐ”๊ฟ” ๋ณด๋ ค๊ณ  ํ•œ๋‹ค ^_^

 

 

++ ์ด์ „ ๊ธ€ ์˜ฌ๋ฆฌ๊ณ  ๋‹ค์Œ ๋‚  ์˜ฌ๋ฆด๋ ค๊ณ  ํ–ˆ๋Š”๋ฐ

๋‹ค๋ฅธ๊ฑธ ๋จผ์ € ์˜ฌ๋ ธ๋”๋‹ˆ ์žŠํ˜€์งˆ ๋ป” ํ–ˆ๋‹ค

 


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

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

 

1) unique_ptr

2) shared_ptr (์˜ค๋Š˜ํ• ๊ฑฐ)

3) weak_ptr

 

 

1-1) unique_ptr์ด ๋ญ์˜€๋”๋ผ (๋งํฌ ์ฒจ๋ถ€ ^^)

 

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

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

 

๋‘ ๋ฒˆ์งธ, make_unique() ๋˜๋Š” new๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค

 

์„ธ ๋ฒˆ์งธ,  ๊ณ ์œ ํ•œ ์†Œ์œ ๊ถŒ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ณต์‚ฌ ๋Œ€์‹  move๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•œ๋‹ค

 


 

2. shared_ptr

unique_ptr์€ ๊ณ ์œ ํ•œ.... ์œ ๋‹ˆํฌํ•œ ๋Š๋‚Œ์ด ๋“œ๋Š” ์ด๋ฆ„์ด์—ˆ๋Š”๋ฐ

shared๋Š” ๋ญ”๊ฐ€ ๊ณต์œ ํ•˜๋Š” ๊ณต์œ ๋  ๊ฒƒ ๊ฐ™์€ ๋Š๋‚Œ์ด ๋“ ๋‹ค

 

 

๋ฐ”๋กœ ์‚ฌ์šฉ ์˜ˆ์‹œ๋กœ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜๊ฒ ๋‹ค

 

#include <memory>
#include <iostream>

using namespace std;

int main ( )
{
    std::shared_ptr<int> ptr = std::make_shared<int>(10);
    cout << ptr << endl;
    cout << *ptr << endl;

    return 0;
}

 

์™€~ ptr ์ถœ๋ ฅํ•˜๋ฉด 10์ด ๋‚˜์˜ค๊ฒ ์ง€? ใ…‹ ํ•˜๋ฉด ์•ˆ๋œ๋‹ค

์˜ˆ์‹œ์—์„œ ์‚ฌ์šฉํ•œ ๊ฒƒ ์ฒ˜๋Ÿผ, ptr ์ž์ฒด๋ฅผ ์ถœ๋ ฅํ•˜๋ฉด ํฌ์ธํ„ฐ๊ธฐ ๋•Œ๋ฌธ์—

ํฌ์ธํ„ฐ์˜ ์ฃผ์†Œ๊ฐ’์ด ๋‚˜์˜ค๊ณ ,

* ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฅดํ‚ค๋Š” ๊ฐ’์ธ 10์ด ๋‚˜์˜จ๋‹ค

๋˜ํ•œ shared๋ผ๋Š” ์ด๋ฆ„์—์„œ ๋Š๋‚Œ์ด ์˜ค๋“ฏ์ด

unique_ptr๊ณผ ๋‹ค๋ฅด๊ฒŒ shared_ptr์€ ๋ณต์‚ฌ(copy)๊ฐ€ ๋˜๊ณ 

๊ฐ™์€ ๊ฐ’์„ ๊ฐ€๋ฅดํ‚ค๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค

 

int main ( )
{
    std::shared_ptr<int> ptr = std::make_shared<int>(10);
    cout << *ptr << endl;

    std::shared_ptr<int> ptr_cp = ptr;
    cout << *ptr_cp << endl;

    return 0;
}

 

 

ptr_cp๋ผ๋Š” shared_ptr์— ptr์˜ ๊ฐ’์„ ํ• ๋‹นํ•ด๋„

์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ ๋ชจ์Šต์ด๋‹ค

์š”๊ฑธ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค

 

 

๊ฐ“MS

 

Diagram1์„ ๋ณด๋ฉด, Control Block์ด๋ž€๊ฑธ p1์ด ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋‹ค

์—ฌ๊ธฐ์„œ p1์€ shared_ptr ํƒ€์ž…์˜ ๋ณ€์ˆ˜๋ฅผ ๋œปํ•˜๊ณ 

ํฌ์ธํ„ฐ๋‹ˆ๊นŒ ์ฃผ์†Œ ๊ฐ’์„ ๊ฐ€์ง„๋‹ค(์ฐธ์กฐํ•œ๋‹ค)๊ณ  ์ดํ•ดํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค

 

 

2-1) Reference Count (์ฐธ์กฐ ํšŸ์ˆ˜)

 

shared_ptr์—๋Š” ์ฐธ์กฐํšŸ์ˆ˜๋ผ๋Š” ๊ฐœ๋…์ด ์žˆ๋‹ค

unique_ptr๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ shared_ptr๋Š” ์ž๊ธฐ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” ๋™์•ˆ

์†Œ์œ ๊ถŒ์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค

(ํฌ์ธํ„ฐ์˜ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์„ ๋•Œ๋Š” get()์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค)

์†Œ์œ ๊ถŒ์ด ๋Š˜์–ด๋‚  ๋•Œ(์‚ฌ์šฉ ํšŸ์ˆ˜๊ฐ€ ๋Š˜์–ด๋‚  ๋•Œ) ์ฐธ์กฐ ํšŸ์ˆ˜๋Š” ์ฆ๊ฐ€ํ•œ๋‹ค

 

๋˜ํ•œ shared_ptr ๊ฐ์ฒด๋ฅผ ์†Œ์œ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋ฌด๋„ ์—†์œผ๋ฉด ์ฐธ์กฐ ํšŸ์ˆ˜๋„ 0์ด ๋  ์ˆ˜ ์žˆ๋‹ค

์ฐธ์กฐ ํšŸ์ˆ˜๋Š” use_count() ๋กœ ๊ฐ€์ ธ์˜ค๋ฉด ๋œ๋‹ค

 

๊ทธ๋ฆผ์œผ๋กœ ๋ด๋ณด์žฅ

 

 

 

Diagram2๋ฅผ ๋ณด๋ฉด, Diagram 1์ฒ˜๋Ÿผ Control Block์„ p1๊ณผ p2๊ฐ€ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋‹ค

๋‹ค๋ฅธ ์ ์€, p1๋„ ์ฐธ์กฐํ•˜๊ณ  → ์ฐธ์กฐ ์นด์šดํŠธ +1

p2๋„ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— → ์ฐธ์กฐ ์นด์šดํŠธ +1

๊ทธ๋ฆผ ์ƒ๋‹จ์˜ Ref count๊ฐ€ 2๊ฐ€ ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค

 

์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” p1๊ณผ p2๊ฐ€ ๋ชจ๋‘ ์‚ฌ๋ผ์ง€๋ฉด, Ref count๋„ 0์ด ๋˜๋Š”๋ฐ

๊ทธ๋Ÿฌ๋ฉด ์ž๋™์œผ๋กœ ์‚ญ์ œ๊ฐ€ ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋”ฐ๋กœ ํ•ด์ œํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค

 

๋ง์ด ์–ด๋ ต์ง€๋งŒ ์ฝ”๋“œ๋กœ ์ถœ๋ ฅ ๋ช‡ ๋ฒˆ  ํ•ด๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋‹ค

 

int main ( )
{
    std::shared_ptr<int> ptr = std::make_shared<int>(10);
    cout << *ptr << endl;

    std::shared_ptr<int> ptr_cp = ptr;
    cout << *ptr_cp << endl;

    std::shared_ptr<int> ptr_cp2 = ptr_cp;

    cout << "Ref Count: " << ptr.use_count() << endl;

    return 0;
}

 

๊ฒฐ๊ณผ ์ง 

 

ptr์˜ use_count๊ฐ€ 3์œผ๋กœ ์ถœ๋ ฅ์ด ๋๋‹ค

 

1) ptr์— ๋Œ€ํ•ด make_shared๋กœ ๋งŒ๋“ค์–ด์„œ ์นด์šดํŠธ ์ฆ๊ฐ€

2) ptr ํฌ์ธํ„ฐ๋ฅผ ptr_cp์—์„œ๋„ ๊ฐ–๊ณ  ์žˆ์Œ

3) ptr์˜ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ–๋Š” ptr_cp์˜ ํฌ์ธํ„ฐ๋ฅผ ptr_cp2์—์„œ๋„ ๊ฐ–๊ณ  ์žˆ์Œ

(ptr์˜ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ€์ง)

 

์˜ˆ์‹œ๋ฅผ ํ•˜๋‚˜ ๋” ๋“ค์–ด๋ณด๊ฒ ๋‹ค

ptr์„ ์‚ฌ์šฉ์•ˆํ•˜๋ฉด ์ฐธ์กฐ ์นด์šดํŠธ๋„ ์ž๋™์œผ๋กœ ์ค„์–ด๋“œ๋Š”์ง€

ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ, ์ง€์—ญ ํ•จ์ˆ˜์—์„œ

shared_ptr ํฌ์ธํ„ฐ๋ฅผ ๋ณต์‚ฌํ•˜๋„๋ก ํ•ด๋ณด๊ฒ ๋‹ค

 

void func(shared_ptr<int> ptr)
{
    std::shared_ptr<int> ptr_cp = ptr;
    cout << *ptr_cp << endl;

    std::shared_ptr<int> ptr_cp2 = ptr_cp;
    cout << __func__ << "::Ref Count: " << ptr.use_count() << endl;
}

int main ( )
{
    std::shared_ptr<int> ptr = std::make_shared<int>(10);
    cout << *ptr << endl;

    func(ptr);
    cout << __func__ << "::Ref Count: " << ptr.use_count() << endl;

    return 0;
}

 

 

main์—์„œ๋Š” shared_ptr ๊ฐ์ฒด์ธ ptr๋งŒ ๋งŒ๋“ค์–ด์คฌ๊ณ 

func() ํ•จ์ˆ˜์—์„œ ๊ฐ’ ๋ณต์‚ฌ๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค

๊ทธ๋ฆฌ๊ณ  ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํฌ์ธํ„ฐ๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด์„œ Ref count๋„ ํ•˜๋‚˜ ๋” ์ฆ๊ฐ€ํ–ˆ๋‹ค

 

ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์—๋Š” func()์—์„œ ์ˆ˜ํ–‰ํ•œ ์ฐธ์กฐ๋Š” ์—†์–ด์กŒ๊ธฐ ๋•Œ๋ฌธ์—

main์—์„œ๋Š” ๋‹ค์‹œ Ref Count๊ฐ€ 1๋กœ ๋˜์—ˆ๋‹ค

 

 

 

3. shared_ptr๋ฅผ value๋กœ ๊ฐ–๋Š” ์ž๋ฃŒ๊ตฌ์กฐ

 

shared_ptr์€ map์ด๋‚˜ vector ๊ฐ™์€ ์ž๋ฃŒ๊ตฌ์กฐ์—์„œ

value ๊ฐ’์œผ๋กœ๋„ ๋งŽ์ด ์“ฐ์ธ๋‹ค

 

map์„ ๊ฐ์‹ธ๋Š” ๋ชจ์–‘์œผ๋กœ๋„ ์“ฐ์ด๊ธด ํ•˜์ง€๋งŒ

ํฌ์ธํ„ฐ๋กœ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด ๊ตณ์ด?

 

๋ฐ”๋กœ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด์„œ ์„ค๋ช…ํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค

 

#include <map>

int main ( )
{
    map<string, shared_ptr<int>> mapTest;

    auto ptr = make_shared<int>(10);
    cout << __func__ << "::Ref Count: " << ptr.use_count() << endl;

    mapTest["first"] = ptr;

    cout << __func__ << "::Ref Count: " << ptr.use_count() << endl;

    for( auto const &val : mapTest )
    {
        cout << val.first << ": " << *val.second << endl;
    }

    return 0;
}

 

 

์ด๋ ‡๊ฒŒ map์˜ value ๊ฐ’์œผ๋กœ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค

map์ด ์†Œ๋ฉธ๋œ๋‹ค๋ฉด value๋กœ ์žˆ๋Š” shared_ptr์˜ ์†Œ๋ฉธ์ž๋„ ์ž๋™์œผ๋กœ ๋ถˆ๋ฆฐ๋‹ค

๋”ฐ๋กœ ๊ด€๋ฆฌ ์•ˆํ•ด์ค˜๋„ ๋จ

 

ํŽธํ•˜๊ฒŒ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ

ํฌ์ธํ„ฐ๋Š” ํฌ์ธํ„ฐ๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ ์กฐ์‹ฌํ•˜๋„๋ก ํ•˜์ž

 


์ฐธ๊ณ ์ž๋ฃŒ

 

https://en.cppreference.com/w/cpp/memory/shared_ptr/use_count

 

std::shared_ptr::use_count - cppreference.com

long use_count() const noexcept; Returns the number of different shared_ptr instances (this included) managing the current object. If there is no managed object, โ€‹0โ€‹ is returned. In multithreaded environment, the value returned by use_count is approxim

en.cppreference.com