shared_ptr_allocate_shared

shared_ptr_allocate_shared (std::allocate_shared)

<memory> 헤더에 정의되어 있어요. 주어진 할당자 alloc의 복사본을 사용해 객체를 위한 메모리를 할당하고, 제공된 인자들로 객체를 초기화해 만들어요. 새로 만든 객체를 관리하는 std::shared_ptr을 돌려줘요. C++11부터 도입됐어요.

출처: cppreference

본문

template< class T, class Alloc, class... Args >
shared_ptr<T> allocate_shared( const Alloc& alloc, Args&&... args );   // (1) since C++11, constexpr since C++26

template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc, std::size_t N );     // (2) since C++20, constexpr since C++26

template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc );                    // (3) since C++20, constexpr since C++26

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) since C++20, constexpr since C++26

template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc,
                               const std::remove_extent_t<T>& u );      // (5) since C++20, constexpr since C++26

template< class T, class Alloc >
shared_ptr<T> allocate_shared_for_overwrite( const Alloc& alloc );      // (6) since C++20, constexpr since C++26

template< class T, class Alloc >
shared_ptr<T> allocate_shared_for_overwrite( const Alloc& alloc,
                                             std::size_t N );           // (7) since C++20, constexpr since C++26
  • (1) T 타입 객체. 비-배열 타입일 때만 참여. std::allocator_traits<Alloc>::construct로 구성.
  • (2) std::remove_extent_t<T>[N] 타입 객체. 무한 배열 타입일 때만 참여. 각 요소는 기본 초기값.
  • (3) T 타입 객체, 각 요소 기본 초기값. 유한 배열 타입일 때만 참여.
  • (4)(5) 각 요소가 초기값 u를 갖는 배열 버전.
  • (6)(7) allocate_shared_for_overwrite. 객체를 ::new로 기본-초기화해 덮어쓰게 내버려둠. 배열 요소의 초기값은 미지정.

std::allocate_shared는 보통 한 번만 할당하고 T 객체와 제어 블록을 같은 메모리 블록에 둬요(표준은 권고하며 필수는 아니지만 알려진 구현은 모두 이렇게 해요). alloc의 복사본이 제어 블록 일부로 저장되어 shared·weak 참조 수가 모두 0이 되면 해제에 사용돼요.

std::shared_ptr 생성자와 달리 allocate_shared는 별도의 커스텀 삭제자를 받지 않아요. 제공된 할당자가 제어 블록과 T 객체의 파괴 및 공유 메모리 블록의 해제 전부에 사용돼요.

반환값

T 타입 또는 무한 배열 타입이면 std::remove_extent_t<T>[N](C++20) 객체에 대한 std::shared_ptr. 반환된 r에 대해 r.get()은 비-널 포인터, r.use_count()는 1이에요.

예외

Alloc::allocate() 또는 T의 생성자가 던지는 예외를 던질 수 있어요. 예외 발생 시 (1)은 효과가 없고, 배열 구성 중 예외 시 이미 초기화된 요소들이 역순으로 파괴돼요 (C++20).

예제

#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)
        v.emplace_back(std::allocate_shared<Value>(allocator, i));
    for (const auto& sp : v)
        sp->print();
}

출력:

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

주의 (Notes)

기능 테스트 매크로 __cpp_lib_smart_ptr_for_overwrite(C++20)는 allocate_shared_for_overwrite 오버로드 (6,7)를 나타내요.

더 알아보기 (Learn more)

cppreference