C++ 使用std::make_唯一自定义初始化数组

C++ 使用std::make_唯一自定义初始化数组,c++,unique-ptr,C++,Unique Ptr,假设我想创建一个std::unique_ptr,但我想将创建的数组初始化为自定义值:{1,2,3,4,5} 我可以使用new并将原始指针传递给std::unique\u ptr构造函数,然后该构造函数将拥有并管理它 std::unique_ptr<int[]> ptr{ new int[5]{1,2,3,4,5} }; std::unique_ptr ptr{new int[5]{1,2,3,4,5}; 我的问题是,对于std::make_unique,是否也可以这样做?对于st

假设我想创建一个
std::unique_ptr
,但我想将创建的数组初始化为自定义值:
{1,2,3,4,5}

我可以使用
new
并将原始指针传递给
std::unique\u ptr
构造函数,然后该构造函数将拥有并管理它

std::unique_ptr<int[]> ptr{ new int[5]{1,2,3,4,5} };
std::unique_ptr ptr{new int[5]{1,2,3,4,5};

我的问题是,对于
std::make_unique
,是否也可以这样做?

对于
std::make_unique
,有3个重载:

template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args );     // (1) for non-array type

template< class T >
unique_ptr<T> make_unique( std::size_t size );   // (2) for array type with unknown bounds

template< class T, class... Args >
/* unspecified */ make_unique( Args&&... args ) = delete; // (3) for array type with known bounds.
模板
唯一的_ptr使_唯一(Args&&…Args);//(1) 对于非数组类型
模板
独一无二的,独一无二的(标准::尺寸(2) 对于具有未知边界的数组类型
模板<类T,类。。。Args>
/*未指定*/make_unique(Args&&…Args)=delete;//(3) 对于具有已知边界的数组类型。
它们都不支持您想要的行为(请注意,第三个函数标记为
delete

您可以分别使用(2)和初始化数组元素,或者切换到
std::vector
并使用(1)。

(特别是推荐
vector
的部分,如果可能)是正确的,但我只想添加另一个选项

如果数组边界已知且固定,而不是未知的绑定可变长度C样式数组,则可以从C样式数组切换到
std::array
,以实现此目的。启用优化后,运行时的工作就相当了(在
-O1
g++
中,它正确地确定它可以内联整个内容,使其成为一个简单的分配,然后直接在新分配的内存中填充各个元素,而不是试图在堆栈上生成一个
数组
,然后将其作为参数传递给
make_unique
,从而h最终将调用move构造函数,从而有效地将
std::array
)的工作加倍

std::unique_ptr<int[]> ptr{ new int[5]{1,2,3,4,5} };
与C样式数组相比,
std::array
的主要优点和缺点是,无论哪种方式,最终结果都是
std::unique_ptr
,而不是
std::unique_ptr
;一方面,指向的数组的大小永远不会改变(以后不能用指向
std::array
的指针替换
unique\u ptr
内容),但另一方面,大小是在编译时嵌入的,因此您和编译器都知道大小

由于编译器知道大小,因此在调用以参数类型为模板的函数时,您不必手动传递指针和大小。模板将在编译时专用于您的精确大小(这允许编译器在循环展开或使用常量循环边界时做出更好的优化选择)一点也不超过尺寸

对于未模板化且需要C样式参数的函数(例如,它们需要一个数组,并接收第一个元素的
int*
和长度的
size\t
),您只需将
&ptr[0]
作为指针传递,将
ptr->size()
作为长度传递。由于大小是一个编译时常量,因此可以免费获得(不要在多个位置重复数组的大小,也不要仅仅为了避免干涸而定义毫无用处的命名常量;该大小是类型定义的一部分,在内联使用,在上下文中具有明显的意义),没有性能开销(它应该与编译时大小完全一致,就像您自己键入大小一样,但如果以后更改
数组的大小,则不会出现数字不同步的风险)

再一次,为了绝对清楚,这里的正确答案几乎总是“使用
std::vector
,这基本上是
std::unique\u ptr

  • 根据需要自动调整
    int[]
    的大小
  • 大大简化了常见用例
  • 当大小没有被主动更改时,
    std::vector
    可以与C风格的数组API配合使用(将
    vec.data()
    /
    &vec[0]
    /
    &vec.at(0)
    作为指针,将
    vec.size()
    作为长度),您不必担心管理大小调整/重新分配这是一个痛苦的C++,当你不能使用<代码> ReLoC/<代码>而不放弃访问<代码>删除[]/COD> >时,理论上可以稍微慢一点,但是在99%的情况下,它将比任何必须重新执行<代码>矢量 >的行为要快得多——因为代码< >矢量< /代码>被调谐到“只是工作”。以最大速度运行,而您自己的代码不太可能经过仔细调整)

    auto ptr = std::make_unique<std::array<int, 5>>(std::array<int, 5>{1,2,3,4,5});
    
    auto ptr = std::make_unique<std::array<int, 5>>(std::experimental::make_array(1,2,3,4,5));