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)를 나타내요.