unique_ptr_make_unique

unique_ptr_make_unique (std::make_unique)

<memory> 헤더에 정의되어 있어요. 타입 T의 객체를 구성하고 그것을 std::unique_ptr로 감싸요. C++14부터 도입됐어요.

출처: cppreference

본문

template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args );   // (1) C++14, 비-배열 타입만
template< class T >
unique_ptr<T> make_unique( std::size_t size );  // (2) C++14, 경계 미지정 배열만
template< class T, class... Args >
/* unspecified */ make_unique( Args&&... args ) = delete;   // (3) 경계 지정 배열만
template< class T >
unique_ptr<T> make_unique_for_overwrite();     // (4) C++20, 비-배열 타입만
template< class T >
unique_ptr<T> make_unique_for_overwrite( std::size_t size );  // (5) C++20, 경계 미지정 배열만
template< class T, class... Args >
/* unspecified */ make_unique_for_overwrite( Args&&... args ) = delete;  // (6) 경계 지정 배열만

타입 T의 객체를 구성하고 그것을 std::unique_ptr로 감싸요.

  • (1) 비-배열 타입 T를 구성. argsT의 생성자에 전달돼요. T가 배열형이 아니면 참여. unique_ptr<T>(new T(std::forward<Args>(args)...))와 동등.
  • (2) 주어진 동적 크기의 배열을 구성. 요소는 값 초기화돼요. T가 경계 미지정 배열이면 참여. unique_ptr<T>(new std::remove_extent_t<T>[size]())와 동등.
  • (3,6) 경계 지정 배열의 구성은 금지돼요.
  • (4) (1)과 같지만 객체가 기본 초기화돼요. unique_ptr<T>(new T)와 동등.
  • (5) (2)와 같지만 배열이 기본 초기화돼요. unique_ptr<T>(new std::remove_extent_t<T>[size])와 동등.

반환값

타입 T의 인스턴스에 대한 std::unique_ptr.

예외

std::bad_alloc 또는 T의 생성자가 던지는 예외를 던질 수 있어요. 예외 발생 시 이 함수는 효과가 없어요.

예제

#include <cstddef>
#include <iomanip>
#include <iostream>
#include <memory>
#include <utility>

struct Vec3
{
    int x, y, z;
    Vec3(int x = 0, int y = 0, int z = 0) noexcept : x(x), y(y), z(z) {}
    friend std::ostream& operator<<(std::ostream& os, const Vec3& v)
    {
        return os << "{ x=" << v.x << ", y=" << v.y << ", z=" << v.z << " }";
    }
};

template<typename OutputIt>
OutputIt fibonacci(OutputIt first, OutputIt last)
{
    for (int a = 0, b = 1; first != last; ++first)
    {
        *first = b;
        b += std::exchange(a, b);
    }
    return first;
}

int main()
{
    std::unique_ptr<Vec3> v1 = std::make_unique<Vec3>();       // 기본 생성자
    std::unique_ptr<Vec3> v2 = std::make_unique<Vec3>(0, 1, 2); // (0,1,2)
    std::unique_ptr<Vec3[]> v3 = std::make_unique<Vec3[]>(5);   // 5개 배열

    // 초기화되지 않은 10개 int 배열을 만들어 피보나치로 채움
    std::unique_ptr<int[]> i1 = std::make_unique_for_overwrite<int[]>(10);
    fibonacci(i1.get(), i1.get() + 10);

    std::cout << "make_unique<Vec3>():      " << *v1 << '\n'
              << "make_unique<Vec3>(0,1,2): " << *v2 << '\n'
              << "make_unique<Vec3[]>(5):   ";
    for (std::size_t i = 0; i < 5; ++i)
        std::cout << std::setw(i ? 30 : 0) << v3[i] << '\n';
    std::cout << '\n';

    std::cout << "make_unique_for_overwrite<int[]>(10), fibonacci(...): [" << i1[0];
    for (std::size_t i = 1; i < 10; ++i)
        std::cout << ", " << i1[i];
    std::cout << "]\n";
}

출력:

make_unique<Vec3>():      { x=0, y=0, z=0 }
make_unique<Vec3>(0,1,2): { x=0, y=1, z=2 }
make_unique<Vec3[]>(5):   { x=0, y=0, z=0 }
                          { x=0, y=0, z=0 }
                          { x=0, y=0, z=0 }
                          { x=0, y=0, z=0 }
                          { x=0, y=0, z=0 }

make_unique_for_overwrite<int[]>(10), fibonacci(...): [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

주의 (Notes)

std::make_shared(에 std::allocate_shared가 있는)와 달리 std::make_unique에는 할당자 인식 대응물이 없어요.

더 알아보기 (Learn more)

cppreference