Namespaces
Variants

std:: allocate_shared, std:: allocate_shared_for_overwrite

From cppreference.net
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 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,

const std:: remove_extent_t < T > & u ) ;
(4) (C++20부터)
template < class T, class Alloc >

shared_ptr < T > allocate_shared ( const Alloc & alloc,

const std:: remove_extent_t < T > & u ) ;
(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,

std:: size_t N ) ;
(7) (C++20부터)

지정된 인수들로 객체를 초기화하고 (지정되지 않은 value_type 에 대해 재바인딩된) alloc 의 복사본을 사용하여 객체에 대한 메모리를 할당합니다. 새로 생성된 객체를 관리하는 std::shared_ptr 객체를 반환합니다.

1) 객체는 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 > 타입의 해당 객체를 가리키는 포인터입니다.
위 설명에서, a Alloc 타입이며, alloc 의 잠재적으로 리바운드된 복사본입니다.

이 오버로드는 T 가 배열 타입이 아닌 경우에만 오버로드 해결에 참여합니다.

(since C++20)
2) 객체는 std:: remove_extent_t < T > [ N ] 타입입니다. 각 요소는 기본 초기값을 가집니다.
이 오버로드는 T 가 경계가 없는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
3) 객체는 T 타입입니다. 각 요소는 기본 초기값을 가집니다.
이 오버로드는 T 가 경계 있는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
4) 객체는 std:: remove_extent_t < T > [ N ] 타입입니다. 각 요소는 u 초기값을 가집니다.
이 오버로드는 T 가 경계가 없는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
5) 객체는 T 타입입니다. 각 요소는 초기값 u 을 가집니다.
이 오버로드는 T 가 경계 있는 배열 타입인 경우에만 오버로드 해결에 참여합니다.
6) 객체는 T 타입입니다.
  • 만약 T 가 배열 타입이 아닌 경우, 객체는 :: new ( pv ) T 와 같은 방식으로 생성됩니다. 여기서 pv T 타입 객체를 담을 수 있는 저장 공간을 가리키는 void * 포인터입니다. 객체가 파괴되어야 하는 경우, pt - > ~T ( ) 와 같은 방식으로 파괴됩니다. 여기서 pt T 타입의 해당 객체를 가리키는 포인터입니다.
  • 만약 T 가 경계가 지정된 배열 타입인 경우, 각 요소의 초기값은 지정되지 않습니다.
이 오버로드는 T 가 배열 타입이 아니거나 경계가 지정된 배열 타입인 경우에만 오버로드 해결에 참여합니다.
7) 객체의 타입은 std:: remove_extent_t < T > [ N ] 입니다. 각 요소의 초기값은 지정되지 않습니다.
이 오버로드는 T 가 경계가 없는 배열 타입인 경우에만 오버로드 해결에 참여합니다.

목차

배열 요소 초기화 및 소멸

아래 설명에서, a Alloc 타입이며, alloc 의 잠재적으로 리바운드된 복사본입니다.

U 타입의 배열 요소는 주소의 오름차순으로 초기화됩니다.

  • U 가 배열 타입이 아닌 경우, 각 요소는 다음 표현식과 같이 생성됩니다. 여기서 pu std:: remove_cv_t < U > * std:: remove_cv_t < U > 타입의 객체를 보관할 수 있는 저장소에 대한 포인터이고, pv void * U 타입의 객체를 보관할 수 있는 저장소에 대한 포인터입니다:
2,3) std:: allocator_traits < Alloc > :: construct ( a, pu )
4,5) std:: allocator_traits < Alloc > :: construct ( a, pu, u )
6,7) :: new ( pv ) U
  • 그렇지 않으면, 각 요소의 요소들을 재귀적으로 초기화합니다. 다음 차원에 대해:
  • U std:: remove_extent_t < U > 가 됩니다.
  • 오버로드 (4,5) 에 대해, u u 의 해당 요소가 됩니다.

반환된 std::shared_ptr 이 관리하는 객체의 수명이 종료되거나, 배열 요소의 초기화에서 예외가 발생하면, 초기화된 요소들은 원래 생성 순서의 역순으로 소멸됩니다.

소멸될 비배열 타입 U 의 각 배열 요소에 대해, 다음 표현식과 같이 소멸됩니다:

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부터), std::allocate_shared 는 지원하지 않습니다. 이 기능은 boost::allocate_shared 에서 지원됩니다.

(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)