在C++中,是否有一种方法可以静态初始化动态分配的数组?

18

在C++中,我可以静态初始化一个数组,例如:

int a[] = { 1, 2, 3 };
有没有一种简单的方法将动态分配的数组初始化为一组立即值?
int *p = new int[3];
p = { 1, 2, 3 }; // syntax error

我必须手动复制这些值吗?


你反对什么?写代码来初始化向量的必要性?复制所需的时间?请注意,任何编译器的技巧来初始化动态分配的数组都会涉及相同的复制,因为无法保证分配的内存具有完全正确的内容。 - David Thornley
如果性能至关重要,为什么还要动态分配内存呢?为什么要通过指针进行间接引用?既然您已经在编译时“静态初始化”了数组,那么矩阵的维度肯定是已知的吧? - fredoverflow
我没有反对任何事情,只是在询问。我正在使用自己的矩阵类,它将数据存储在动态分配的数组中,我认为如果我可以在不手动复制数据的情况下初始化该数组会很好。 :) - neuviemeporte
@Fred:这只是一个矩阵的测试用例,以查看它是否为某些预定义输入提供正确的结果。在一般情况下,大小在编译时是未知的。 - neuviemeporte
1
好的,那么你可能正在处理非常大的矩阵?如果是这样的话,根据这些矩阵的性质,可能会有比数组或向量更好的数据结构。 - fredoverflow
6个回答

31

你可以在C++0x中:

int* p = new int[3] { 1, 2, 3 };
...
delete[] p;

但我更喜欢向量:

std::vector<int> v { 1, 2, 3 };

如果您没有C++0x编译器,boost可以帮助你:

#include <boost/assign/list_of.hpp>
using boost::assign::list_of;

vector<int> v = list_of(1)(2)(3);

5
对于 std::vector 给个 +1。仍然使用自己的动态数组的原因是什么? - sbi
6
如果你甚至不信任std::vector,也许你应该彻底放弃C++,转而使用汇编语言。 - fredoverflow
6
@Poni: 访问向量并没有必要比访问数组慢得可以被检测出来,因此任何声称如此的测试仅适用于特定编译器、编译选项和库。请记住,实现可以进行额外的检查,当处于调试模式或选择某些编译器选项时,很多实现都会这样做。 - David Thornley
2
@neuviemeporte:哪些访问器函数?如果你觉得你绝对需要保持控制,你可以像这样写:int *ptr = &v[0]... ptr[i] ...,因为(截至2003年)矢量内容存储是被保证连续的。只要确保在向量大小增加时更改ptr即可。 - David Thornley
3
@Poni曾在SO上与我们争论过这个问题,但 并不是 真的。请看这里 (https://dev59.com/-nA65IYBdhLWcg3wuhIR),我们得出结论:向量和内置数组之间没有区别。 - Martin York
显示剩余22条评论

12

你需要显式地为动态数组的每个元素赋值(例如在for或while循环中)

不过,语法int *p = new int [3]();可以将所有元素初始化为0(值初始化$8.5/5)


4
为了避免无尽的push_back,我通常会初始化一个tr1::array,并从结果中创建一个std::vector(或任何其他容器std容器)。
const std::tr1::array<T, 6> values = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(values.begin(), values.end());

这里唯一的烦恼是您必须明确提供值的数量。
当然,这也可以不使用tr1 :: array来完成;
const T values[] = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(&values[0], &values[sizeof(values)/sizeof(values[0])]);

虽然你不必显式提供元素数量,但我更喜欢第一个版本。

1

使用辅助变量:

const int p_data[] = {1, 2, 3};
int* p = (int*)memcpy(new int[3], p_data, sizeof(p_data));

或者,一行代码

int p_data[] = {1, 2, 3},  *p = (int*)memcpy(new int[3], p_data, sizeof(p_data));

3
通常情况下(并且是一个好习惯),在函数调用中不应该动态分配对象(也就是说,永远不应该在函数参数中调用 new)。原因是函数参数的求值顺序是未指定的,所以你可能会动态分配内存,然后另一个参数的求值可能会抛出异常,这时那个动态分配的对象就会被泄漏。Herb Sutter 有更多的解释 - James McNellis
+1 虽然这有点晦涩,只适用于 POD。 - fredoverflow
1
James McNellis,通用规则只是“通用”规则。它们需要有解释,以确保规则适用于特定情况。在这种情况下,一切都很好。 - Abyx
2
在这种特定情况下,是“可以的”;但是编写高质量的代码意味着编写符合众所周知、安全的模式的代码(特别是当该模式不会造成任何额外开销时)。这段代码不可能通过任何合理的关键代码审查(或者,至少不应该)。 - James McNellis
@James:不幸的是,有些人为了“性能”这头神牛而牺牲了所有优秀的软件原则。 - fredoverflow

1

不,你不能以同样的方式初始化动态创建的数组。

大多数情况下,您会发现自己在使用动态分配时,静态初始化并没有太多意义。例如当您有包含数千个项目的数组时。因此,这通常不是一个大问题。


-1

从未听说过有这样的事情是可能的,那将是很不错的。

请记住,在代码中以那种方式初始化数组。

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

......只会让你更容易编写代码,而不是提高性能。毕竟,无论你怎么做,CPU 都会负责将值分配给数组。


那行代码不会生成任何代码...它是编译时初始化。 - joeking

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