堆上数组的初始化

21

如何在堆上手动初始化数组的值? 如果数组是局部变量(在栈中),可以通过以下简洁而易于操作的方式轻松完成:

int myArray[3] = {1,2,3};

不幸的是,以下代码

int * myArray = new int[3];
myArray = {1,2,3};

编译时会输出一个错误

error: expected primary-expression before ‘{’ token
error: expected `;' before ‘{’ token

我是否必须使用cycle,还是可以像这样不太优雅的方式?

myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 3;

从你的示例看,你想用值1到N + 1填充数组元素0..N。使用for循环可以很好地完成这个任务。你的实际意图是什么? - EvilTeach
7个回答

6
今天可以使用以下语法来实现这一点:
int * myHeapArray = new int [3] {1, 2, 3};

请注意,您必须将您分配的结构的大小与初始化列表的大小匹配。

由于我正在回答几年前发布的问题,值得一提的是,现代C++不鼓励使用newdelete和本机(或裸指针)。相反,更倾向于使用诸如std::unique_ptrstd::shared_ptr之类的处理程序,因为它们会自动释放它们拥有的内存(检查RAII习惯用法)。

在这种特定情况下,std::vector将提供所有这些功能:堆分配数据,使用初始化列表(例如{1, 2, 3}),处理程序和移动语义等其他功能。

对于堆栈分配的数组,您可以考虑使用std::array,如果需要的话。


非常好的答案,谢谢。 - Peter Wilson

5

这很有趣:将数组推入向量中

但是,如果您不满意,请尝试以下操作:

#include <algorithm>
...


const int length = 32;

int stack_array[length] = { 0 ,32, 54, ... }
int* array = new int[length];

std::copy(stack_array, stack_array + length, &array[0]);

1
你犯了一个错误,应该是 std::copy(stack_array, stack_array+5, &array[0]); - qed
VLA(可变长度数组)不是C++标准的一部分。 - Nayana Adassuriya
VLAs in C++ so -1 - cat

3

{1,2,3}是一种非常有限的语法,仅适用于POD结构初始化(显然C风格数组也被认为是其中之一)。你唯一能做的就像int x[] = {1,2,3};int x[3] = {1,2,3};,但你既不能做int x[3]; x={1,2,3};,也不能在任何其他地方使用{1,2,3}

如果你在使用C ++,最好使用类似std :: vector之类的东西而不是C风格数组,因为它们被认为是危险的 - 例如,你无法知道它们的大小,并且必须使用delete [] 而不是普通的delete来删除它们。虽然使用std :: vector仍然存在同样的初始化问题。如果我经常使用这样的初始化,我可能会创建一个宏将其赋值给一个虚拟变量,然后将内存复制到目标。

编辑:你也可以像这样做(仍然建议使用std :: vector):

int* NewArray(int v1, int v2, int v3) { /* allocate and initialize */ }
int* p = NewArray(1,2,3);

但是你将不得不使用不同数量的参数覆盖该函数,或者使用 va_arg,这又是不安全的。

编辑2:我的答案仅适用于C++03,正如其他人提到的,C++0x对此有一些改进。


3

你可以定义常量数组,例如 myConstArray[] = {1, 2, 3} ,并在 new int[3] 后使用 memcpy 进行复制。


5
通常情况下,使用std::copy来复制对象而不是位模式。 - Pete Kirkham
不幸的是,这种方法在最好的情况下效率低下,在最坏的情况下甚至不可能实现(如果类型是一个没有复制/赋值的类)。 - Yttrill
如果类型是一个没有复制/赋值的类,那么根本无法使用常量数组。 - Nickolay Olshevsky

0

你也可以按照以下方式进行初始化:

int * myArray = new int[3];
*myarray=1;
*(myarray+1)=2;
*(myarray+2)=3;

0
如果您想要一个适用于所有类型的通用答案,那么您需要做的是:
1. 使用malloc()或operator new()创建一个未初始化存储的数组,其长度由nelts * sizeof(T)计算得出。 2. 创建一个由每个元素构造函数的参数组成的数组。 3. 使用相应的参数以放置形式对每个元素应用构造函数。
这仅适用于相同构造函数适用于每个元素的情况。如果不是,则需要更复杂的数据结构和算法来为每个元素选择正确的构造函数。
这种情况的特殊情况是使用实际元素的数组并使用复制构造函数,而其中的一种特殊情况是当类型为POD时,您可以只使用memcpy一次性构造所有元素。
如果构造函数需要两个参数,则需要编写一个初始化程序(包装器)。例如:
pair<double> init_data[] = {make_pair(1.0,0.0), make_pair(3.0,4.0)};
void init(void *p, pair<double> d) { new (p) complex(d.first, d.second); }

使用它而不是仅仅使用new(p)。


0

C++0x标准有一个特殊类型叫做initializer_list,并且有一个特殊的语法(表达式类型{1, 2, 3}std::initializer_list<int>)。std::vectorstd::array都可以从中构造,所以你可以写成vector<int> v = {1, 2, 3}

C++98/C++03中没有好的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接