Namespaces
Variants

std:: shared_ptr

From cppreference.net
< cpp โ€Ž | memory
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
ํ—ค๋” ํŒŒ์ผ์— ์ •์˜๋จ <memory>
template < class T > class shared_ptr ;
(C++11๋ถ€ํ„ฐ)

std::shared_ptr ๋Š” ํฌ์ธํ„ฐ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด์˜ ๊ณต์œ  ์†Œ์œ ๊ถŒ์„ ์œ ์ง€ํ•˜๋Š” ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐœ์˜ shared_ptr ๊ฐ์ฒด๊ฐ€ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ์†Œ์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ฐ์ฒด๋Š” ์†Œ๋ฉธ๋˜๊ณ  ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค:

  • ๊ฐ์ฒด๋ฅผ ์†Œ์œ ํ•˜๋Š” ๋งˆ์ง€๋ง‰ ๋‚จ์€ shared_ptr ์ด ํŒŒ๊ดด๋  ๋•Œ;
  • ๊ฐ์ฒด๋ฅผ ์†Œ์œ ํ•˜๋Š” ๋งˆ์ง€๋ง‰ ๋‚จ์€ shared_ptr ์ด operator= ๋˜๋Š” reset() ์„ ํ†ตํ•ด ๋‹ค๋ฅธ ํฌ์ธํ„ฐ๋กœ ์žฌํ• ๋‹น๋  ๋•Œ.

๊ฐ์ฒด๋Š” delete-expression ๋˜๋Š” ์ƒ์„ฑ ์‹œ shared_ptr ์— ์ œ๊ณต๋œ ์‚ฌ์šฉ์ž ์ •์˜ ์‚ญ์ œ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ๊ดด๋ฉ๋‹ˆ๋‹ค.

A shared_ptr ๋Š” ๊ฐ์ฒด์˜ ์†Œ์œ ๊ถŒ์„ ๊ณต์œ ํ•˜๋ฉด์„œ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ๋ฉค๋ฒ„ ๊ฐ์ฒด๊ฐ€ ์†ํ•œ ๊ฐ์ฒด๋ฅผ ์†Œ์œ ํ•˜๋ฉด์„œ ํ•ด๋‹น ๋ฉค๋ฒ„ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €์žฅ๋œ ํฌ์ธํ„ฐ๋Š” get() , ์—ญ์ฐธ์กฐ ๋ฐ ๋น„๊ต ์—ฐ์‚ฐ์ž๋กœ ์ ‘๊ทผ๋˜๋Š” ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค. ๊ด€๋ฆฌ๋˜๋Š” ํฌ์ธํ„ฐ๋Š” ์‚ฌ์šฉ ์นด์šดํŠธ๊ฐ€ 0์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ์‚ญ์ œ์ž(deleter)์— ์ „๋‹ฌ๋˜๋Š” ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค.

shared_ptr ๋Š” ๊ฐ์ฒด๋ฅผ ์†Œ์œ ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ, ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ ์ด๋ฅผ empty ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค(๋ณ„์นญ ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋œ ๊ฒฝ์šฐ, ๋นˆ shared_ptr ์ด null์ด ์•„๋‹Œ ์ €์žฅ๋œ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).

shared_ptr ์˜ ๋ชจ๋“  ํŠน์ˆ˜ํ™”๋Š” CopyConstructible , CopyAssignable , ๊ทธ๋ฆฌ๊ณ  LessThanComparable ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜๋ฉฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ bool ๋กœ ๋ณ€ํ™˜ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ๋ฉค๋ฒ„ ํ•จ์ˆ˜(๋ณต์‚ฌ ์ƒ์„ฑ์ž์™€ ๋ณต์‚ฌ ํ• ๋‹น ์—ฐ์‚ฐ์ž ํฌํ•จ)๋Š” ์„œ๋กœ ๋‹ค๋ฅธ shared_ptr ๊ฐ์ฒด์—์„œ ์ถ”๊ฐ€์ ์ธ ๋™๊ธฐํ™” ์—†์ด ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๋“ค์ด ๋ณต์‚ฌ๋ณธ์ด๊ณ  ๋™์ผํ•œ ๊ฐ์ฒด์˜ ์†Œ์œ ๊ถŒ์„ ๊ณต์œ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์—ฌ๋Ÿฌ ์‹คํ–‰ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™๊ธฐํ™” ์—†์ด ๋™์ผํ•œ shared_ptr ๊ฐ์ฒด์— ์ ‘๊ทผํ•˜๊ณ  ๊ทธ ์ค‘ ํ•˜๋‚˜๋ผ๋„ shared_ptr ์˜ ๋น„์ƒ์ˆ˜ ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ฐ์ดํ„ฐ ๊ฒฝ์Ÿ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค; std::atomic<shared_ptr> ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๊ฒฝ์Ÿ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชฉ์ฐจ

๋ฉค๋ฒ„ ํƒ€์ž…

๋ฉค๋ฒ„ ํƒ€์ž… ์ •์˜
element_type
T (C++17 ์ด์ „)
std:: remove_extent_t < T > (C++17 ์ดํ›„)
weak_type (C++17 ์ดํ›„) std:: weak_ptr < T >

๋ฉค๋ฒ„ ํ•จ์ˆ˜

์ƒˆ๋กœ์šด shared_ptr ์„ ์ƒ์„ฑํ•จ
(public member function)
๋” ์ด์ƒ shared_ptr ์ด ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์œผ๋ฉด ์†Œ์œ ํ•œ ๊ฐ์ฒด๋ฅผ ํŒŒ๊ดดํ•จ
(public member function)
shared_ptr ์„ ํ• ๋‹นํ•จ
(public member function)
์ˆ˜์ •์ž
๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ต์ฒดํ•จ
(public member function)
๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋“ค์„ ๊ตํ™˜ํ•จ
(public member function)
๊ด€์ฐฐ์ž
์ €์žฅ๋œ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•จ
(public member function)
์ €์žฅ๋œ ํฌ์ธํ„ฐ๋ฅผ ์—ญ์ฐธ์กฐํ•จ
(public member function)
(C++17)
์ €์žฅ๋œ ๋ฐฐ์—ด์— ๋Œ€ํ•œ ์ธ๋ฑ์Šค ์ ‘๊ทผ์„ ์ œ๊ณตํ•จ
(public member function)
๋™์ผํ•œ ๊ด€๋ฆฌ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” shared_ptr ๊ฐ์ฒด์˜ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•จ
(public member function)
(until C++20)
๊ด€๋ฆฌ ๊ฐ์ฒด๊ฐ€ ํ˜„์žฌ shared_ptr ๊ฐ์ฒด์— ์˜ํ•ด์„œ๋งŒ ๊ด€๋ฆฌ๋˜๋Š”์ง€ ํ™•์ธํ•จ
(public member function)
์ €์žฅ๋œ ํฌ์ธํ„ฐ๊ฐ€ null์ด ์•„๋‹Œ์ง€ ํ™•์ธํ•จ
(public member function)
shared pointer์— ๋Œ€ํ•œ ์†Œ์œ ์ž ๊ธฐ๋ฐ˜ ์ˆœ์„œ ์ง€์ •์„ ์ œ๊ณตํ•จ
(public member function)
(C++26)
shared pointer์— ๋Œ€ํ•œ ์†Œ์œ ์ž ๊ธฐ๋ฐ˜ ํ•ด์‹ฑ์„ ์ œ๊ณตํ•จ
(public member function)
shared pointer์— ๋Œ€ํ•œ ์†Œ์œ ์ž ๊ธฐ๋ฐ˜ ๋™๋“ฑ ๋น„๊ต๋ฅผ ์ œ๊ณตํ•จ
(public member function)

๋น„๋ฉค๋ฒ„ ํ•จ์ˆ˜

์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” shared_ptr์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค
(ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ)
ํ• ๋‹น์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ• ๋‹น๋œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” shared_ptr์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค
(ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ)
์ €์žฅ๋œ ํฌ์ธํ„ฐ์— static_cast , dynamic_cast , const_cast , ๋˜๋Š” reinterpret_cast ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค
(ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ)
์†Œ์œ ํ•œ ๊ฒฝ์šฐ ์ง€์ •๋œ ํƒ€์ž…์˜ ์‚ญ์ œ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
(ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ)
(C++20์—์„œ ์ œ๊ฑฐ๋จ) (C++20์—์„œ ์ œ๊ฑฐ๋จ) (C++20์—์„œ ์ œ๊ฑฐ๋จ) (C++20์—์„œ ์ œ๊ฑฐ๋จ) (C++20์—์„œ ์ œ๊ฑฐ๋จ) (C++20)
๋‹ค๋ฅธ shared_ptr ๋˜๋Š” nullptr ์™€ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค
(ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ)
์ €์žฅ๋œ ํฌ์ธํ„ฐ์˜ ๊ฐ’์„ ์ถœ๋ ฅ ์ŠคํŠธ๋ฆผ์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค
(ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ)
std::swap ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํŠน์ˆ˜ํ™”ํ•ฉ๋‹ˆ๋‹ค
(ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ)
std::shared_ptr ์— ๋Œ€ํ•œ ์›์ž์  ์—ฐ์‚ฐ ์ „๋ฌธํ™”
(ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ)

ํ—ฌํผ ํด๋ž˜์Šค

์›์ž์  ๊ณต์œ  ํฌ์ธํ„ฐ
(ํด๋ž˜์Šค ํ…œํ”Œ๋ฆฟ ํŠน์ˆ˜ํ™”)
std::shared_ptr ์— ๋Œ€ํ•œ ํ•ด์‹œ ์ง€์›
(ํด๋ž˜์Šค ํ…œํ”Œ๋ฆฟ ํŠน์ˆ˜ํ™”)

์ถ”๋ก  ๊ฐ€์ด๋“œ (C++17๋ถ€ํ„ฐ)

์ฐธ๊ณ  ์‚ฌํ•ญ

๊ฐ์ฒด์˜ ์†Œ์œ ๊ถŒ์€ ๋‹ค๋ฅธ shared_ptr ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š” ์ƒ์„ฑ์ž๋‚˜ ํ• ๋‹น ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๊ณต์œ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ƒˆ๋กœ์šด shared_ptr ์ด ๋‹ค๋ฅธ shared_ptr ์ด ๋ณด์œ ํ•œ ์›์‹œ ๊ธฐ๋ณธ ํฌ์ธํ„ฐ๋งŒ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋œ๋‹ค๋ฉด, ์ด ์ƒˆ๋กœ์šด shared_ptr ์€ ์ž์‹ ์ด ์†Œ์œ ํ•œ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅธ shared_ptr ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ณด์œ ํ•˜๊ณ  ์žˆ์ง€ ์•Š๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด (ํ›„์† ํ• ๋‹น์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ํ•œ) ์†Œ๋ฉธ ์‹œ ๋™์ผํ•œ ๊ฐ์ฒด์— ๋Œ€ํ•ด deleter๊ฐ€ ๋ฐ˜๋ณต์ ์œผ๋กœ ์ ์šฉ๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•ฉ๋‹ˆ๋‹ค.

std::shared_ptr ๋Š” incomplete type T ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ raw pointer๋กœ๋ถ€ํ„ฐ์˜ ์ƒ์„ฑ์ž ( template < class Y > shared_ptr ( Y * ) ) ์™€ template < class Y > void reset ( Y * ) ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋Š” ์™„์ „ํ•œ ํƒ€์ž…์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋กœ๋งŒ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ( std::unique_ptr ์€ incomplete type์— ๋Œ€ํ•œ raw pointer๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ์Œ์— ์œ ์˜ํ•˜์‹ญ์‹œ์˜ค).

T ๋Š” ํ•จ์ˆ˜ ํƒ€์ž…์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ์ด ๊ฒฝ์šฐ ๊ฐ์ฒด ํฌ์ธํ„ฐ ๋Œ€์‹  ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ํ•ด๋‹น ํ•จ์ˆ˜๋“ค์ด ์ฐธ์กฐ๋˜๋Š” ๋™์•ˆ ๋ฉ”๋ชจ๋ฆฌ์— ์œ ์ง€๋˜๋„๋ก ํ•  ๋•Œ ์ข…์ข… ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค:

void del(void(*)()) {}
void fun() {}
int main()
{
    std::shared_ptr<void()> ee(fun, del);
    (*ee)();
}

๊ตฌํ˜„ ์ฐธ๊ณ  ์‚ฌํ•ญ

์ผ๋ฐ˜์ ์ธ ๊ตฌํ˜„์—์„œ, shared_ptr ์€ ๋‹จ์ง€ ๋‘ ๊ฐœ์˜ ํฌ์ธํ„ฐ๋งŒ ๋ณด์œ ํ•ฉ๋‹ˆ๋‹ค:

  • ์ €์žฅ๋œ ํฌ์ธํ„ฐ ( get() ์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’);
  • control block ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ.

์ œ์–ด ๋ธ”๋ก์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์„ ๋ณด์œ ํ•˜๋Š” ๋™์ ์œผ๋กœ ํ• ๋‹น๋œ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค:

  • ๊ด€๋ฆฌ๋˜๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ ๋˜๋Š” ๊ด€๋ฆฌ๋˜๋Š” ๊ฐ์ฒด ์ž์ฒด;
  • ์‚ญ์ œ์ž (ํƒ€์ž… ์‚ญ์ œ๋จ);
  • ํ• ๋‹น์ž (ํƒ€์ž… ์‚ญ์ œ๋จ);
  • ๊ด€๋ฆฌ๋˜๋Š” ๊ฐ์ฒด๋ฅผ ์†Œ์œ ํ•˜๋Š” shared_ptr ์˜ ๊ฐœ์ˆ˜;
  • ๊ด€๋ฆฌ๋˜๋Š” ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” weak_ptr ์˜ ๊ฐœ์ˆ˜.

shared_ptr ๊ฐ€ std::make_shared ๋˜๋Š” std::allocate_shared ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ƒ์„ฑ๋  ๋•Œ, ์ œ์–ด ๋ธ”๋ก๊ณผ ๊ด€๋ฆฌ ๊ฐ์ฒด ๋ชจ๋‘์— ๋Œ€ํ•œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‹จ์ผ ํ• ๋‹น์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ด€๋ฆฌ ๊ฐ์ฒด๋Š” ์ œ์–ด ๋ธ”๋ก์˜ ๋ฐ์ดํ„ฐ ๋ฉค๋ฒ„ ๋‚ด๋ถ€์— ์ธํ”Œ๋ ˆ์ด์Šค ๋ฐฉ์‹์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. shared_ptr ์ƒ์„ฑ์ž ์ค‘ ํ•˜๋‚˜๋ฅผ ํ†ตํ•ด shared_ptr ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ๋Š” ๊ด€๋ฆฌ ๊ฐ์ฒด์™€ ์ œ์–ด ๋ธ”๋ก์„ ๋ณ„๋„๋กœ ํ• ๋‹นํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ œ์–ด ๋ธ”๋ก์€ ๊ด€๋ฆฌ ๊ฐ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

shared_ptr ๊ฐ€ ์ง์ ‘ ๋ณด์œ ํ•˜๋Š” ํฌ์ธํ„ฐ๋Š” get() ์— ์˜ํ•ด ๋ฐ˜ํ™˜๋˜๋Š” ํฌ์ธํ„ฐ์ด๋ฉฐ, ์ œ์–ด ๋ธ”๋ก์ด ๋ณด์œ ํ•˜๋Š” ํฌ์ธํ„ฐ/๊ฐ์ฒด๋Š” ๊ณต์œ  ์†Œ์œ ์ž ์ˆ˜๊ฐ€ 0์— ๋„๋‹ฌํ•  ๋•Œ ์‚ญ์ œ๋  ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค. ์ด ๋‘ ํฌ์ธํ„ฐ๋Š” ๋ฐ˜๋“œ์‹œ ๋™์ผํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

shared_ptr ์˜ ์†Œ๋ฉธ์ž๋Š” ์ œ์–ด ๋ธ”๋ก์˜ ๊ณต์œ  ์†Œ์œ ์ž ์ˆ˜๋ฅผ ๊ฐ์†Œ์‹œํ‚ต๋‹ˆ๋‹ค. ์ด ์นด์šดํ„ฐ๊ฐ€ 0์— ๋„๋‹ฌํ•˜๋ฉด, ์ œ์–ด ๋ธ”๋ก์€ ๊ด€๋ฆฌ๋˜๋Š” ๊ฐ์ฒด์˜ ์†Œ๋ฉธ์ž๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ œ์–ด ๋ธ”๋ก์€ std::weak_ptr ์นด์šดํ„ฐ ๋˜ํ•œ 0์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ์ž์‹ ์„ ํ• ๋‹น ํ•ด์ œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด ๊ตฌํ˜„์—์„œ๋Š” ๋™์ผํ•œ ์ œ์–ด ๋ธ”๋ก์„ ๊ฐ€๋ฆฌํ‚ค๋Š” shared ํฌ์ธํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ weak ํฌ์ธํ„ฐ์˜ ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค ( [1] , [2] ).

์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑ์‹œํ‚ค๊ธฐ ์œ„ํ•ด, ์ฐธ์กฐ ์นด์šดํ„ฐ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ std::atomic::fetch_add ์™€ std::memory_order_relaxed ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค (์ œ์–ด ๋ธ”๋ก์„ ์•ˆ์ „ํ•˜๊ฒŒ ํŒŒ๊ดดํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ์†Œ ์‹œ์—๋Š” ๋” ๊ฐ•ํ•œ ์ˆœ์„œ ์ง€์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค).

์˜ˆ์ œ

#include <chrono>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
using namespace std::chrono_literals;
struct Base
{
    Base() { std::cout << "Base::Base()\n"; }
    // ์ฐธ๊ณ : ๋น„๊ฐ€์ƒ ์†Œ๋ฉธ์ž๊ฐ€ ์—ฌ๊ธฐ์„œ๋Š” ๊ดœ์ฐฎ์Œ
    ~Base() { std::cout << "Base::~Base()\n"; }
};
struct Derived : public Base
{
    Derived() { std::cout << "Derived::Derived()\n"; }
    ~Derived() { std::cout << "Derived::~Derived()\n"; }
};
void print(auto rem, std::shared_ptr<Base> const& sp)
{
    std::cout << rem << "\n\tget() = " << sp.get()
              << ", use_count() = " << sp.use_count() << '\n';
}
void thr(std::shared_ptr<Base> p)
{
    std::this_thread::sleep_for(987ms);
    std::shared_ptr<Base> lp = p; // ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•จ, ๊ณต์œ  use_count๊ฐ€ ์ฆ๊ฐ€ํ•ด๋„
                                  // ์•ˆ์ „
    {
        static std::mutex io_mutex;
        std::lock_guard<std::mutex> lk(io_mutex);
        print("์Šค๋ ˆ๋“œ ๋‚ด ๋กœ์ปฌ ํฌ์ธํ„ฐ:", lp);
    }
}
int main()
{
    std::shared_ptr<Base> p = std::make_shared<Derived>();
    print("๊ณต์œ  Derived ์ƒ์„ฑ (Base์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋กœ)", p);
    std::thread t1{thr, p}, t2{thr, p}, t3{thr, p};
    p.reset(); // ๋ฉ”์ธ์—์„œ ์†Œ์œ ๊ถŒ ํ•ด์ œ
    print("3๊ฐœ ์Šค๋ ˆ๋“œ ๊ฐ„ ๊ณต์œ  ์†Œ์œ ๊ถŒ ๋ฐ ๋ฉ”์ธ์—์„œ ์†Œ์œ ๊ถŒ ํ•ด์ œ:", p);
    t1.join();
    t2.join();
    t3.join();
    std::cout << "๋ชจ๋“  ์Šค๋ ˆ๋“œ ์™„๋ฃŒ, ๋งˆ์ง€๋ง‰ ์Šค๋ ˆ๋“œ๊ฐ€ Derived๋ฅผ ์‚ญ์ œํ•จ.\n";
}

๊ฐ€๋Šฅํ•œ ์ถœ๋ ฅ:

Base::Base()
Derived::Derived()
Created a shared Derived (as a pointer to Base)
	get() = 0x118ac30, use_count() = 1
Shared ownership between 3 threads and released ownership from main:
	get() = 0, use_count() = 0
Local pointer in a thread:
	get() = 0x118ac30, use_count() = 5
Local pointer in a thread:
	get() = 0x118ac30, use_count() = 4
Local pointer in a thread:
	get() = 0x118ac30, use_count() = 2
Derived::~Derived()
Base::~Base()
All threads completed, the last one deleted Derived.

์˜ˆ์ œ

#include <iostream>
#include <memory>
struct MyObj
{
    MyObj() { std::cout << "MyObj ์ƒ์„ฑ๋จ\n"; }
    ~MyObj() { std::cout << "MyObj ์†Œ๋ฉธ๋จ\n"; }
};
struct Container : std::enable_shared_from_this
**๋ณ€์—ญ ๊ฒฐ๊ณผ:**
std::enable_shared_from_this
**์„ค๋ช…:**
- HTML ํƒœ๊ทธ์™€ ์†์„ฑ์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
- C++ ๊ด€๋ จ ์šฉ์–ด(`std::enable_shared_from_this`)๋Š” ๋ฒˆ์—ญํ•˜์ง€ ์•Š๊ณ  ์›๋ฌธ์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.
- ํƒœ๊ทธ ๋‚ด๋ถ€์˜ ํ…์ŠคํŠธ๋„ ๋ชจ๋‘ ๋ณด์กด๋˜์—ˆ์Šต๋‹ˆ๋‹ค.<Container> // ์ฐธ๊ณ : public ์ƒ์†
{
    std::shared_ptr<MyObj> memberObj;
    void CreateMember() { memberObj = std::make_shared<MyObj>(); }
    std::shared_ptr<MyObj> GetAsMyObj()
    {
        // ๋ฉค๋ฒ„์— ๋Œ€ํ•œ ๋ณ„์นญ ๊ณต์œ  ํฌ์ธํ„ฐ ์‚ฌ์šฉ
        return std::shared_ptr<MyObj>(shared_from_this(), memberObj.get());
    }
};
#define COUT(str) std::cout << '\n' << str << '\n'
#define DEMO(...) std::cout << #__VA_ARGS__ << " = " << __VA_ARGS__ << '\n'
int main()
{
    COUT("๊ณต์œ  ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ");
    std::shared_ptr<Container> cont = std::make_shared<Container>();
    DEMO(cont.use_count());
    DEMO(cont->memberObj.use_count());
    COUT("๋ฉค๋ฒ„ ์ƒ์„ฑ");
    cont->CreateMember();
    DEMO(cont.use_count());
    DEMO(cont->memberObj.use_count());
    COUT("๋‹ค๋ฅธ ๊ณต์œ  ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑํ•˜๊ธฐ");
    std::shared_ptr<Container> cont2 = cont;
    DEMO(cont.use_count());
    DEMO(cont->memberObj.use_count());
    DEMO(cont2.use_count());
    DEMO(cont2->memberObj.use_count());
    COUT("GetAsMyObj");
    std::shared_ptr<MyObj> myobj1 = cont->GetAsMyObj();
    DEMO(myobj1.use_count());
    DEMO(cont.use_count());
    DEMO(cont->memberObj.use_count());
    DEMO(cont2.use_count());
    DEMO(cont2->memberObj.use_count());
    COUT("๋ณ„์นญ ๊ฐ์ฒด ๋ณต์‚ฌ ์ค‘");
    std::shared_ptr<MyObj> myobj2 = myobj1;
    DEMO(myobj1.use_count());
    DEMO(myobj2.use_count());
    DEMO(cont.use_count());
    DEMO(cont->memberObj.use_count());
    DEMO(cont2.use_count());
    DEMO(cont2->memberObj.use_count());
    COUT("cont2 ์žฌ์„ค์ • ์ค‘");
    cont2.reset();
    DEMO(myobj1.use_count());
    DEMO(myobj2.use_count());
    DEMO(cont.use_count());
    DEMO(cont->memberObj.use_count());
    COUT("myobj2 ์žฌ์„ค์ • ์ค‘");
    myobj2.reset();
    DEMO(myobj1.use_count());
    DEMO(cont.use_count());
    DEMO(cont->memberObj.use_count());
    COUT("์ปจํŠธ ์žฌ์„ค์ • ์ค‘");
    cont.reset();
    DEMO(myobj1.use_count());
    DEMO(cont.use_count());
}

์ถœ๋ ฅ:

๊ณต์œ  ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ
cont.use_count() = 1
cont->memberObj.use_count() = 0
๋ฉค๋ฒ„ ์ƒ์„ฑ
MyObj constructed
cont.use_count() = 1
cont->memberObj.use_count() = 1
๋‹ค๋ฅธ ๊ณต์œ  ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ
cont.use_count() = 2
cont->memberObj.use_count() = 1
cont2.use_count() = 2
cont2->memberObj.use_count() = 1
GetAsMyObj
myobj1.use_count() = 3
cont.use_count() = 3
cont->memberObj.use_count() = 1
cont2.use_count() = 3
cont2->memberObj.use_count() = 1
๋ณ„์นญ ๊ฐ์ฒด ๋ณต์‚ฌ
myobj1.use_count() = 4
myobj2.use_count() = 4
cont.use_count() = 4
cont->memberObj.use_count() = 1
cont2.use_count() = 4
cont2->memberObj.use_count() = 1
cont2 ๋ฆฌ์…‹
myobj1.use_count() = 3
myobj2.use_count() = 3
cont.use_count() = 3
cont->memberObj.use_count() = 1
myobj2 ๋ฆฌ์…‹
myobj1.use_count() = 2
cont.use_count() = 2
cont->memberObj.use_count() = 1
cont ๋ฆฌ์…‹
myobj1.use_count() = 1
cont.use_count() = 0
MyObj destructed

์ฐธ๊ณ  ํ•ญ๋ชฉ

(C++11)
๊ณ ์œ  ๊ฐ์ฒด ์†Œ์œ ๊ถŒ ์˜๋ฏธ๋ก ์„ ๊ฐ€์ง„ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ
(ํด๋ž˜์Šค ํ…œํ”Œ๋ฆฟ)
(C++11)
std::shared_ptr ์ด ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ์•ฝํ•œ ์ฐธ์กฐ
(ํด๋ž˜์Šค ํ…œํ”Œ๋ฆฟ)