std:: allocate_shared, std:: allocate_shared_for_overwrite
|
헤더에 정의됨
<memory>
|
||
|
template
<
class
T,
class
Alloc,
class
...
Args
>
shared_ptr < T > allocate_shared ( const Alloc & alloc, Args && ... args ) ; |
(1) | (C++11부터) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared ( const Alloc & alloc, std:: size_t N ) ; |
(2) | (C++20부터) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared ( const Alloc & alloc ) ; |
(3) | (C++20부터) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared
(
const
Alloc
&
alloc,
std::
size_t
N,
|
(4) | (C++20부터) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared
(
const
Alloc
&
alloc,
|
(5) | (C++20부터) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared_for_overwrite ( const Alloc & alloc ) ; |
(6) | (C++20부터) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared_for_overwrite
(
const
Alloc
&
alloc,
|
(7) | (C++20부터) |
지정된 인수들로 객체를 초기화하고 (지정되지 않은
value_type
에 대해 재바인딩된)
alloc
의 복사본을 사용하여 객체에 대한 메모리를 할당합니다. 새로 생성된 객체를 관리하는
std::shared_ptr
객체를 반환합니다.
T
타입이며, 마치
std::
allocator_traits
<
Alloc
>
::
construct
( a, pt, ( std:: forward < Args > ( args ) ... ) 와 같이 생성됩니다. 여기서 pt 는 std:: remove_cv_t < T > * 타입의 객체를 저장하기에 적합한 저장 공간을 가리키는 포인터입니다. 객체가 파괴되어야 할 경우, 마치 std:: allocator_traits < Alloc > :: destroy ( a, pt ) 와 같이 파괴됩니다. 여기서 pt 는 std:: remove_cv_t < T > 타입의 해당 객체를 가리키는 포인터입니다.
Alloc
타입이며,
alloc
의 잠재적으로 리바운드된 복사본입니다.
|
이 오버로드는
|
(since C++20) |
T
가 경계가 없는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
T
타입입니다. 각 요소는 기본 초기값을 가집니다.
T
가 경계 있는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
T
가 경계가 없는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
T
타입입니다. 각 요소는 초기값
u
을 가집니다.
T
가 경계 있는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
T
타입입니다.
-
만약
T가 배열 타입이 아닌 경우, 객체는 :: new ( pv ) T 와 같은 방식으로 생성됩니다. 여기서 pv 는T타입 객체를 담을 수 있는 저장 공간을 가리키는 void * 포인터입니다. 객체가 파괴되어야 하는 경우, pt - > ~T ( ) 와 같은 방식으로 파괴됩니다. 여기서 pt 는T타입의 해당 객체를 가리키는 포인터입니다. -
만약
T가 경계가 지정된 배열 타입인 경우, 각 요소의 초기값은 지정되지 않습니다.
T
가 배열 타입이 아니거나 경계가 지정된 배열 타입인 경우에만 오버로드 해결에 참여합니다.
T
가 경계가 없는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
배열 요소 초기화 및 소멸
아래 설명에서,
a
는
2,3)
std::
allocator_traits
<
Alloc
>
::
construct
(
a, pu
)
4,5)
std::
allocator_traits
<
Alloc
>
::
construct
(
a, pu, u
)
6,7)
::
new
(
pv
)
U
반환된 std::shared_ptr 이 관리하는 객체의 수명이 종료되거나, 배열 요소의 초기화에서 예외가 발생하면, 초기화된 요소들은 원래 생성 순서의 역순으로 소멸됩니다.
소멸될 비배열 타입
2-5)
std::
allocator_traits
<
Alloc
>
::
destroy
(
a, pu
)
, 여기서
pu
는
U
타입의 해당 배열 요소에 대한
U
*
포인터입니다.
6,7)
pu
-
>
~U
(
)
, 여기서
pu
는
U
타입의 해당 배열 요소에 대한 포인터입니다.
|
(C++20부터) |
매개변수
| alloc | - | 사용할 Allocator |
| args... | - |
T
인스턴스 생성에 사용할 인수 목록
|
| N | - | 사용할 배열 크기 |
| u | - | 배열의 모든 요소를 초기화할 초기값 |
반환값
std::shared_ptr
타입
T
의 객체에 대한
또는
std::
remove_extent_t
<
T
>
[
N
]
만약
T
가 무제한 배열 타입인 경우
(C++20부터)
.
반환된 std::shared_ptr r 에 대해, r. get ( ) 는 널이 아닌 포인터를 반환하고 r. use_count ( ) 는 1 을 반환합니다.
예외
Alloc
::
allocate
(
)
또는
T
의 생성자에서 발생하는 예외를 던질 수 있습니다. 예외가 발생하면,
(1)
은 아무런 효과를 가지지 않습니다.
배열 생성 중 예외가 발생하면, 이미 초기화된 요소들은 역순으로 소멸됩니다
(C++20부터)
.
참고 사항
이러한 함수들은 일반적으로 참조 카운트와 같은 내부 관리 구조를 허용하기 위해 sizeof ( T ) 보다 더 많은 메모리를 할당합니다.
std::make_shared
와 마찬가지로, 이 함수는 일반적으로 단 한 번의 할당만 수행하며, 할당된 메모리 블록에
T
객체와 제어 블록을 함께 배치합니다(표준에서는 이를 권장하지만 요구하지는 않으며, 알려진 모든 구현체들이 이를 따릅니다).
alloc
의 복사본은 제어 블록의 일부로 저장되어, 공유 참조 카운트와 약한 참조 카운트가 모두 0에 도달하면 이를 해제하는 데 사용됩니다.
std::shared_ptr
의
constructors
와 달리,
std::allocate_shared
는 별도의 사용자 정의 삭제자를 허용하지 않습니다: 제공된 할당자는 제어 블록과
T
객체의 소멸, 그리고 이들의 공유 메모리 블록의 할당 해제에 사용됩니다.
|
std::shared_ptr
는 배열 타입을 지원하지만( C++17부터),
|
(C++20 이전) |
생성자가
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()
호출이 이 원시 포인터 생성자로 생성된
std::shared_ptr
와 소유권을 공유하도록 보장합니다.
위 코드의 테스트
ptr
-
>
weak_this
.
expired
(
)
는
weak_this
가 이미 소유자를 가리키고 있을 경우 재할당되지 않도록 보장합니다. 이 테스트는 C++17부터 필수적으로 요구됩니다.
| 기능 테스트 매크로 | 값 | 표준 | 기능 |
|---|---|---|---|
__cpp_lib_smart_ptr_for_overwrite
|
202002L
|
(C++20) |
기본 초기화를 사용한 스마트 포인터 생성 (
std::allocate_shared_for_overwrite
,
std::make_shared_for_overwrite
,
std::make_unique_for_overwrite
); 오버로드
(
6,7
)
|
예제
#include <cstddef> #include <iostream> #include <memory> #include <memory_resource> #include <vector> class Value { int i; public: Value(int i) : i(i) { std::cout << "Value(), i = " << i << '\n'; } ~Value() { std::cout << "~Value(), i = " << i << '\n'; } void print() const { std::cout << "i = " << i << '\n'; } }; int main() { // 단조 버퍼 리소스를 사용하는 다형성 할당자 생성 std::byte buffer[sizeof(Value) * 8]; std::pmr::monotonic_buffer_resource resource(buffer, sizeof(buffer)); std::pmr::polymorphic_allocator<Value> allocator(&resource); std::vector<std::shared_ptr<Value>> v; for (int i{}; i != 4; ++i) // 사용자 정의 할당자와 함께 std::allocate_shared 사용 v.emplace_back(std::allocate_shared<Value>(allocator, i)); for (const auto& sp : v) sp->print(); } //< 모든 shared_ptr은 범위를 벗어날 때 자동으로 정리됩니다.
출력:
Value(), i = 0 Value(), i = 1 Value(), i = 2 Value(), i = 3 i = 0 i = 1 i = 2 i = 3 ~Value(), i = 0 ~Value(), i = 1 ~Value(), i = 2 ~Value(), i = 3
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 3216 | C++20 |
std::allocate_shared
항상 객체 생성 및 소멸 전에
할당자를 리바인딩함 |
리바인딩은 선택 사항 |
| LWG 4024 | C++20 |
std::allocate_shared_for_overwrite
에서 생성된 객체가
어떻게 소멸되는지 불분명했음 |
명확히 규정됨 |
참고 항목
새로운
shared_ptr
을 생성함
(public member function) |
|
|
새로운 객체를 관리하는 shared pointer를 생성함
(function template) |