动态数组的初始化列表

Initializer list for dynamic arrays?

本文关键字:列表 初始化 数组 动态      更新时间:2023-10-16

可以为静态数组的定义提供初始化列表。例子:

int main()
{
  int int_static[2] = {1,2};
}

是否可以为动态数组提供类似的初始化列表?

int main()
{
  int* int_ptr = new int[2];
}

这更接近我想做的:

struct foo
{
  foo(){}
  foo(void * ptr): ptr_(ptr) {}
  void * ptr_;
};
int main()
{
  foo* foo_ptr = new foo[10];
}

初始化时不应调用默认构造函数,而应调用foo:foo(void*)。

为动态数组提供静态初始化列表在加速器内核的实时编译中可能会很方便,因为加速器内核只有有限的堆栈可用,但同时你用(加速器编译时=主机运行时)静态初始化列表构造对象。

我认为不会(因为这将要求编译器生成额外的代码,即将参数的值复制到堆位置)。我认为c++0x支持其中的一些功能,但我不能使用它。现在我可以用这样一个构念。也许有人知道诀窍……

最好!

在OP发布这个问题的时候,c++ 11的支持可能还不是很普遍,这就是为什么公认的答案说这是不可能的。但是,现在所有主要的c++编译器都应该支持用显式初始化列表初始化动态数组。

语法new int[3] {1, 2, 3}在c++ 11中被标准化。引用cppreference.com上的new expression页面:

new-expression创建的对象按照以下规则初始化:

…如果类型是数组类型,则初始化对象数组:

…如果初始化器是一个用大括号括起来的参数列表,则对数组进行聚合初始化。(因为c++ 11)

因此,根据OP的示例,在使用c++ 11或更新版本时,以下操作是完全合法的:

foo * foo_array = new foo[2] { nullptr, nullptr };

请注意,通过在初始化列表中提供指针,我们实际上是在引导编译器应用foo(void * ptr)构造函数(而不是默认构造函数),这是期望的行为。

不,你不能那样做。

我认为c++不允许这样做,因为允许这样的事情并没有给语言增加任何的特性。换句话说,如果使用静态初始化器对动态数组进行初始化,那么动态数组的意义何在?

动态数组的要点是根据实际需要创建一个大小为N的数组,该数组在运行时已知。也就是说,代码

int *p = new int[2]; 

对我来说没有以下内容有意义:

int *p = new int[N]; //N is known at runtime

如果是这样,那么您如何在静态初始化器中提供元素的数量,因为N直到运行时才知道?

让我们假设你可以这样写:

int *p = new int[2] {10,20}; //pretend this!

但是你写这些有什么好处呢?什么都没有。它的几乎和

一样
int a[] = {10,20};

真正的优点是当您被允许为N元素的数组编写时。但问题是:

 int *p = new int[N] {10,20, ... /*Oops, no idea how far we can go? N is not known!*/ };

不,您必须动态创建元素。

或者,您可以使用本地数组并将其元素复制到动态分配数组的元素上:

int main() {
   int _detail[] = { 1, 2 };
   int * ptr = new int[2];
   std::copy( _detail, _detail+(sizeof detail / sizeof *detail), ptr );
   delete [] ptr;
}

在将所有元素设置为0的限制版本中,您可以在new调用中使用一对额外的括号:

int * ptr = new int[2]();  // will value initialize all elements

但你似乎在寻找不同的东西。

考虑到您的实际类比int更复杂,并且由不同的值构造,它很复杂。如果已有一个数组/向量,并且有正确的默认值,则可以使用迭代器构造vector,或者必须使用位置new。

//vector
int main()
{
  int int_static[2] = {1,2};
  std::vector<int> int_dynamic(int_static, int_static+2);
  //this is what everyone else is saying.  For good reason.
}
//placement new
int function_that_returns_constructed_from_values() {
    return rand();
}
int main() 
{
    int count = 2;
    char *char_dynamic = new char[count * sizeof(int)];
    int *int_dynamic = char_dynamic;
    for(int i=0; i<count; ++i)
        new(int_dynamic+i)int(function_that_returns_constructed_from_values());
    //stuff
    for(int i=0; i<count; ++i)
        (int_dynamic+i)->~int(); //obviously not really int
    delete []char_dynamic;
}

显然,vector是实现此目的的首选方法。

初始化器数据必须在某个地方。

#include <stddef.h>
#include <algorithm>        // std::copy
#include <vector>
typedef ptrdiff_t   Size;
template< class Type, Size n >
Size countOf( Type (&)[n] ) { return n; }
int main()
{
    using namespace std;
    static int const    initData[]  = {1,2};
    static Size const   n           = countOf( initData );
    // Initialization of a dynamically allocated array:
    int*        pArray  = new int[n];
    copy( initData, initData + n, pArray );
    // Initialization of a vector:
    vector<int> v( initData, initData + n );
}

EDIT:修正了上面代码中的一个想法。应要求,我赶紧加了一个例子。所以我写的错误地使用了std::copy的返回值。

干杯,hth。