std::shared_ptr<T>:: shared_ptr
|
constexpr
shared_ptr
(
)
noexcept
;
|
(1) | |
|
constexpr
shared_ptr
(
std::
nullptr_t
)
noexcept
;
|
(2) | |
|
template
<
class
Y
>
explicit shared_ptr ( Y * ptr ) ; |
(3) | |
|
template
<
class
Y,
class
Deleter
>
shared_ptr ( Y * ptr, Deleter d ) ; |
(4) | |
|
template
<
class
Deleter
>
shared_ptr ( std:: nullptr_t ptr, Deleter d ) ; |
(5) | |
|
template
<
class
Y,
class
Deleter,
class
Alloc
>
shared_ptr ( Y * ptr, Deleter d, Alloc alloc ) ; |
(6) | |
|
template
<
class
Deleter,
class
Alloc
>
shared_ptr ( std:: nullptr_t ptr, Deleter d, Alloc alloc ) ; |
(7) | |
|
template
<
class
Y
>
shared_ptr ( const shared_ptr < Y > & r, element_type * ptr ) noexcept ; |
(8) | |
|
template
<
class
Y
>
shared_ptr ( shared_ptr < Y > && r, element_type * ptr ) noexcept ; |
(8) | (C++20 이후) |
|
shared_ptr
(
const
shared_ptr
&
r
)
noexcept
;
|
(9) | |
|
template
<
class
Y
>
shared_ptr ( const shared_ptr < Y > & r ) noexcept ; |
(9) | |
|
shared_ptr
(
shared_ptr
&&
r
)
noexcept
;
|
(10) | |
|
template
<
class
Y
>
shared_ptr ( shared_ptr < Y > && r ) noexcept ; |
(10) | |
|
template
<
class
Y
>
explicit shared_ptr ( const std:: weak_ptr < Y > & r ) ; |
(11) | |
|
template
<
class
Y
>
shared_ptr ( std:: auto_ptr < Y > && r ) ; |
(12) | (C++17에서 제거됨) |
|
template
<
class
Y,
class
Deleter
>
shared_ptr ( std:: unique_ptr < Y, Deleter > && r ) ; |
(13) | |
다양한 포인터 타입으로부터 관리할 객체를 참조하는
shared_ptr
을 생성합니다.
|
아래 설명의 목적상, 포인터 타입
|
(since C++17) |
shared_ptr
을 생성합니다. 즉, 빈
shared_ptr
입니다.
shared_ptr
을
ptr
과 함께 생성합니다.
|
(3,4,6)
의 경우,
|
(C++17 이전) |
|
만약
|
(C++17 이후) |
T
가 배열 타입이 아닌 경우;
delete
[
]
ptr
T
가 배열 타입인 경우
(C++17부터)
.
Y
는 완전한 타입이어야 합니다. delete 표현식은 올바른 형식이어야 하며, 잘 정의된 동작을 가지며 어떤 예외도 던지지 않아야 합니다.
이 생성자는 추가적으로 delete 표현식이 올바른 형식이 아닌 경우 오버로드 해결에 참여하지 않습니다.
(C++17부터)
|
|
(C++17 이전) |
|
이러한 생성자들은 추가적으로 d ( ptr ) 표현식이 올바르게 형성되지 않거나, std:: is_move_constructible_v < D > 가 false 인 경우 오버로드 해결에 참여하지 않습니다. |
(C++17 이후) |
shared_ptr
을 생성하며, 이는
r
의 초기값과 소유권 정보를 공유하지만, 관련 없고 관리되지 않는 포인터
ptr
를 보유합니다. 이
shared_ptr
이 그룹에서 범위를 벗어나는 마지막 포인터인 경우, 원래
r
에 의해 관리되던 객체에 대해 저장된 삭제자를 호출합니다. 그러나 이
shared_ptr
에서
get()
을 호출하면 항상
ptr
의 복사본을 반환합니다. 프로그래머는 이
ptr
이 shared_ptr이 존재하는 동안 유효하게 유지되도록 보장할 책임이 있으며, 이는 일반적인 사용 사례에서
ptr
이
r
에 의해 관리되는 객체의 멤버이거나
r.get()
의 별칭(예: 다운캐스트)인 경우에 해당합니다.
rvalue를 취하는 두 번째 오버로드의 경우,
r
은 비어 있고 호출 후
r.
get
(
)
==
nullptr
입니다.
(C++20부터)
shared_ptr
을 생성합니다.
r
가 객체를 관리하지 않으면,
*
this
도 객체를 관리하지 않습니다. 템플릿 오버로드는
Y*
가
암시적으로 변환 가능하지 않으면
(C++17 이전)
호환되지 않으면
(C++17 이후)
오버로드 해결에 참여하지 않습니다.
shared_ptr
를
r
에서 이동 생성합니다. 생성 후,
*
this
는
r
의 이전 상태 사본을 포함하며,
r
는 비어 있고 저장된 포인터는 null입니다. 템플릿 오버로드는
Y*
가
암시적으로 변환 가능하지 않으면
(C++17 이전)
호환되지 않으면
(C++17 이후)
T*
로 오버로드 해결에 참여하지 않습니다.
shared_ptr
을 생성합니다.
Y*
는
T*
로 암시적으로 변환 가능해야 합니다.
(C++17 이전)
이 오버로드는
Y*
가
T*
와 호환될 때만 오버로드 해결에 참여합니다.
(C++17 이후)
동일한 목적으로
r.
lock
(
)
를 사용할 수 있습니다: 차이점은 이 생성자는 인자가 비어 있을 때 예외를 던지는 반면,
std::
weak_ptr
<
T
>
::
lock
(
)
는 그 경우 빈
std::shared_ptr
을 생성한다는 점입니다.
shared_ptr
을 생성합니다.
Y*
는
T*
로 변환 가능해야 합니다. 생성 후에는
r
이 비어 있게 됩니다.
shared_ptr
을 생성합니다.
r
와 연관된 deleter는 향후 관리 객체 삭제를 위해 저장됩니다.
호출 후
r
는 어떤 객체도 관리하지 않습니다.
std::unique_ptr<Y, Deleter>::pointer
가
compatible with
T*
가 아닌 경우, 이 오버로드는 오버로드 해결에 참여하지 않습니다.
만약
r.
get
(
)
이 null 포인터라면, 이 오버로드는 기본 생성자
(1)
와 동등합니다.
|
(since C++17) |
Deleter
가 참조 타입이라면, 이는
shared_ptr
(
r.
release
(
)
,
std::
ref
(
r.
get_deleter
(
)
)
와 동등합니다. 그렇지 않다면,
shared_ptr
(
r.
release
(
)
, std
::
move
(
r.
get_deleter
(
)
)
)
와 동등합니다.
T
가 배열 타입이 아닐 때, 오버로드
(3,4,6)
은
shared_from_this
를
ptr
와 함께 사용 가능하게 하며, 오버로드
(13)
은
shared_from_this
를
r.
release
(
)
가 반환하는 포인터와 함께 사용 가능하게 합니다.
목차 |
매개변수
| ptr | - | 관리할 객체에 대한 포인터 |
| d | - | 객체를 파괴하는 데 사용할 삭제자 |
| alloc | - | 내부 사용을 위한 데이터 할당에 사용할 할당자 |
| r | - | 소유권을 공유하거나 획득할 다른 스마트 포인터 |
사후 조건
예외
T
가 배열 타입이 아닌 경우 호출하고, 그렇지 않으면
delete
[
]
ptr
를 호출합니다
(C++17부터)
.
참고 사항
생성자가
shared_from_this
을 활성화한다는 것은
U*
타입의 포인터
ptr
을 사용하여
U
가
명확하고 접근 가능한
(C++17부터)
std::enable_shared_from_this
의 특수화인 베이스 클래스를 가지고 있는지 판단하고, 만약 그렇다면 생성자가 다음을 평가한다는 의미입니다:
if
(
ptr
!
=
nullptr
&&
ptr
-
>
weak_this
.
expired
(
)
)
ptr
-
>
weak_this
=
std::
shared_ptr
<
std::
remove_cv_t
<
U
>>
(
*
this,
const_cast
<
std::
remove_cv_t
<
U
>
*
>
(
ptr
)
)
;
.
weak_this
에 대한 할당은 원자적이지 않으며 동일한 객체에 대한 잠재적 동시 접근과 충돌합니다. 이는 향후
shared_from_this()
호출이 이 raw 포인터 생성자로 생성된
std::shared_ptr
와 소유권을 공유하도록 보장합니다.
위 코드의 테스트
ptr
-
>
weak_this
.
expired
(
)
는
weak_this
가 이미 소유자를 가리키고 있을 경우 재할당되지 않도록 보장합니다. 이 테스트는 C++17부터 필수적으로 요구됩니다.
원시 포인터 오버로드는 가리키는 객체의 소유권을 가정합니다. 따라서 이미
shared_ptr
에 의해 관리되는 객체에 대해 원시 포인터 오버로드를 사용하여
shared_ptr
을 생성하는 것은(예:
shared_ptr
(
ptr.
get
(
)
)
), 해당 객체가
std::enable_shared_from_this
에서 파생된 타입인 경우에도 정의되지 않은 동작을 초래할 가능성이 높습니다.
기본 생성자가
constexpr
이므로, 정적 shared_ptr들은
정적 비지역 변수 초기화
과정에서 동적 비지역 초기화가 시작되기 전에 초기화됩니다. 이로 인해 어떤 정적 객체의 생성자에서도 shared_ptr을 안전하게 사용할 수 있습니다.
C++11과 C++14에서는 std:: unique_ptr < T [ ] > 로부터 std:: shared_ptr < T > 를 생성하는 것이 유효합니다:
std::unique_ptr<int[]> arr(new int[1]); std::shared_ptr<int> ptr(std::move(arr));
shared_ptr
가
std::
default_delete
<
T
[
]
>
객체)를
std::unique_ptr
로부터 획득하므로, 배열이 올바르게 해제됩니다.
이것은 C++17에서 더 이상 허용되지 않습니다. 대신 배열 형식인 std:: shared_ptr < T [ ] > 을 사용해야 합니다.
예제
#include <iostream> #include <memory> struct Foo { int id{0}; Foo(int i = 0) : id{i} { std::cout << "Foo::Foo(" << i << ")\n"; } ~Foo() { std::cout << "Foo::~Foo(), id=" << id << '\n'; } }; struct D { void operator()(Foo* p) const { std::cout << "Call delete from function object. Foo::id=" << p->id << '\n'; delete p; } }; int main() { { std::cout << "1) constructor with no managed object\n"; std::shared_ptr<Foo> sh1; } { std::cout << "2) constructor with object\n"; std::shared_ptr<Foo> sh2(new Foo{10}); std::cout << "sh2.use_count(): " << sh2.use_count() << '\n'; std::shared_ptr<Foo> sh3(sh2); std::cout << "sh2.use_count(): " << sh2.use_count() << '\n'; std::cout << "sh3.use_count(): " << sh3.use_count() << '\n'; } { std::cout << "3) constructor with object and deleter\n"; std::shared_ptr<Foo> sh4(new Foo{11}, D()); std::shared_ptr<Foo> sh5(new Foo{12}, [](auto p) { std::cout << "Call delete from lambda... p->id=" << p->id << '\n'; delete p; }); } }
출력:
1) constructor with no managed object 2) constructor with object Foo::Foo(10) sh2.use_count(): 1 sh2.use_count(): 2 sh3.use_count(): 2 Foo::~Foo(), id=10 3) constructor with object and deleter Foo::Foo(11) Foo::Foo(12) Call delete from lambda... p->id=12 Foo::~Foo(), id=12 Call delete from function object. Foo::id=11 Foo::~Foo(), id=11
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 3548 | C++11 |
unique_ptr
로부터의 생성자가
deleter를 복사 생성했음
|
대신 이동 생성함 |
참고 항목
|
새로운 객체를 관리하는 shared_ptr을 생성합니다
(함수 템플릿) |
|
|
할당자를 사용하여 할당된 새로운 객체를 관리하는 shared_ptr을 생성합니다
(함수 템플릿) |
|
|
(C++11)
|
객체가 자신을 참조하는
shared_ptr
을 생성할 수 있도록 합니다
(클래스 템플릿) |