# std::make_unique, std::make_unique_for_overwrite

< cpp‎ | memory‎ | unique ptr

定义于头文件 `<memory>` |  |
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) | (C++14 起) (仅对已知边界数组)
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) | (C++20 起) (仅对已知边界数组)

构造 `T` 类型对象并将其包装进 std::unique_ptr 。

1) 构造非数组类型 `T` 对象。传递参数 `args` 给 `T` 的构造函数。此重载仅若 `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) ，除了默认初始化对象。此重载仅若 `T` 不是数组类型才参与重载决议。函数等价于：

    unique_ptr<T>(new T)

5) 同 (2) ，除了默认初始化数组。此重载仅若 `T` 是未知边界数组才参与重载决议。函数等价于：

    unique_ptr<T>(new std::remove_extent_t<T>[size])

### 参数

args | - | 将要构造的 `T` 实例所用的参数列表。
size | - | 要构造的数组大小

### 返回值

类型 `T` 实例的 std::unique_ptr 。

### 异常

可能抛出 std::bad_alloc 或任何 `T` 的构造函数所抛的异常。若抛出异常，则此函数无效果。

### 可能的实现

版本一
    // C++14 make_unique
    namespace detail {
    template<class>
    constexpr bool is_unbounded_array_v = false;
    template<class T>
    constexpr bool is_unbounded_array_v<T[]> = true;

    template<class>
    constexpr bool is_bounded_array_v = false;
    template<class T, std::size_t N>
    constexpr bool is_bounded_array_v<T[N]> = true;
    } // namespace detail

    template<class T, class... Args>
    std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T>>
    make_unique(Args&&... args)
    {
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
    }

    template<class T>
    std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T>>
    make_unique(std::size_t n)
    {
        return std::unique_ptr<T>(new std::remove_extent_t<T>[n]());
    }

    template<class T, class... Args>
    std::enable_if_t<detail::is_bounded_array_v<T>> make_unique(Args&&...) = delete;
版本二
    // C++20 make_unique_for_overwrite
    template<class T>
        requires !std::is_array_v<T>
    std::unique_ptr<T> make_unique_for_overwrite()
    {
        return std::unique_ptr<T>(new T);
    }

    template<class T>
        requires std::is_unbounded_array_v<T>
    std::unique_ptr<T> make_unique_for_overwrite(std::size_t n)
    {
        return std::unique_ptr<T>(new std::remove_extent_t<T>[n]);
    }

    template<class T, class... Args>
        requires std::is_bounded_array_v<T>
    void make_unique_for_overwrite(Args&&...) = delete;

### 注解

不同于 std::make_shared （它拥有 std::allocate_shared ）， `std::make_unique` 没有具分配器的对应物。 P0211 中提案的 `allocate_unique` 会要求为其返回的 `unique_ptr<T,D>` 创作删除器类型 `D` ，返回类型可能含有分配器对象，并在其 `operator()` 调用 `destroy` 和 `deallocate` 。

### 示例

    #include <iostream>
    #include <memory>

    struct Vec3
    {
        int x, y, z;
        // C++20 起不再需要以下构造函数
        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  << '}';
        }
    };

    int main()
    {
        // 使用默认构造函数。
        std::unique_ptr<Vec3> v1 = std::make_unique<Vec3>();
        // 使用匹配这些参数的构造函数
        std::unique_ptr<Vec3> v2 = std::make_unique<Vec3>(0, 1, 2);
        // 创建指向 5 个元素数组的 unique_ptr
        std::unique_ptr<Vec3[]> v3 = std::make_unique<Vec3[]>(5);

        std::cout << "make_unique<Vec3>():      " << *v1 << '\n'
                  << "make_unique<Vec3>(0,1,2): " << *v2 << '\n'
                  << "make_unique<Vec3[]>(5):   " << '\n';
        for (int i = 0; i < 5; i++) {
            std::cout << "     " << v3[i] << '\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}

### 参阅

(构造函数) | 构造新的`unique_ptr` (公开成员函数)
make_shared make_shared_for_overwrite (C++20) | 创建管理一个新对象的共享指针 (函数模板)