2011-08-19 80 views
7

可以给静态数组定义一个初始化列表。例如:动态数组的初始化列表?

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(无效*)。

有一个动态数组的静态初始值设定项列表可能会适用于即时编译加速器核心的情况,这些加速器核心只有有限的堆栈可用,但同时您构建(加速器编译时间=主机运行时间)静态初始化程序列表。

我假设没有(因为这需要编译器生成额外的代码,即将参数的值复制到堆位置)。我认为C++ 0x支持这一些,但我不能使用它。 现在我可以使用这样的构造。也许有人知道一招......

最好!

回答

9

不,你不能那样做。

我认为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!*/ }; 
+4

为了记录,“动态”并不意味着“可变长度”。这确实是一个“很好的功能”,能够创建一个新的动态对象并将其初始化为已知的初始内容。这正是构造函数为类和结构类型对象所做的。 –

+0

为了澄清,C++中的'dynamic'意味着分配在堆上而不是堆栈上。我广泛使用两个存储器商店,因此有两个初始化器列表工作将非常方便。就像在许多情况下,当我想在堆上创建一个数组列表时,我不得不求助于对象(比如std :: vector)而不是普通数组,因为@MikeHousky说,C++只支持在堆上初始化对象那一刻,不是阵列。这里没有技术或性能问题 - 只是C++的限制。 – holocronweaver

0

无论如何,初始化程序的数据必须在某处。简单地命名它。

例如,

#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:固定在上面的代码中一个thinko。我赶紧在请求中添加示例。所以我所做的错误地使用了从std::copy返回的值。

干杯&心连心,

+0

这不是特别清楚。你能举一个说明性的例子吗? –

+0

@Oli,我想他指的是类似于我在答案中建议的解决方案,只是忽略了所需副本的血淋淋的细节。 –

+0

好的,完成了。我不明白什么不清楚。 –

2

不,你将不得不动态创建的元素。

或者,也可以使用本地阵列和对这些动态分配的阵列的复制其元素:

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 

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

+0

第一句话中的标点符号有点误导;有“固定”。如果您不同意,请回滚。 –

+0

我正在寻找一种方式来调用动态分配的每个元素的构造函数(当然它不只是一个“int”)。但它不是必须调用的标准构造函数。它必须采用1个参数,并且该参数的左值对每个元素都是不同的。 – ritter

+0

不应该_detail是一个int *? –

0

鉴于你是真实的类比int更复杂,并且由不同的值构造,它很复杂。 如果您的现有数组/矢量具有默认值的正确值,或者您必须使用放置位置新,则可以使用迭代器构建矢量。

//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; 
} 

显然,向量是执行此操作的首选方法。

10

当OP发布这个问题时,C++ 11支持可能还不是很流行,这就是为什么接受的答案说这是不可能的。但是,现在应该在所有主要的C++编译器中支持使用显式初始化列表初始化动态数组。

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

由新的表达产生的目的根据下列规则进行初始化:
...
如果类型是数组类型,一个初始化对象阵列:
...
如果初始化程序是一个括号括起来的参数列表,则该数组将被聚合初始化。 (因为C++ 11)

因此,鉴于OP的例子,以下用C++ 11或更高版本时,是完全合法的:

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

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