关于初始化:如何在C ++中使用new运算符初始化内存?

How to initialise memory with new operator in C++?

我刚开始进入C++,我想养成一些好习惯。如果我刚刚用new操作符分配了一个int类型的数组,那么如何在不循环遍历它们的情况下将它们全部初始化为0呢?我应该只使用memset吗?有没有办法做到这一点?


这是一个出人意料的鲜为人知的C++特性(事实证明,没有人把这个作为答案),但是它实际上有一个默认的初始化数组的特殊语法(在技术上,它被称为标准中的"值初始化"):

1
new int[10]();

注意,您必须使用空括号-例如,您不能使用(0)或任何其他表达式(这就是为什么它只对默认初始化有用)。

这是由ISO C++ 03 5.3.4(Exp.New)/15明确表示的:

A new-expression that creates an object of type T initializes that object as follows:

...

  • If the new-initializer is of the form (), the item is value-initialized (8.5);

并且不限制允许这样做的类型,而(expression-list)表单则被同一节中的其他规则显式限制,这样它就不允许数组类型。


假设你真的想要一个数组而不是一个STD::vector,"C++方式"就是这个。

1
2
3
4
5
#include  

int* array = new int[n]; // Assuming"n" is a pre-existing variable

std::fill_n(array, n, 0);

但请注意,在引擎盖下,这实际上只是一个循环,它将每个元素分配给0(除了具有硬件级支持的特殊体系结构之外,实际上没有其他方法可以做到这一点)。


有许多方法可以分配一个内部类型的数组,所有这些方法都是正确的,尽管选择哪一个方法取决于…

手动初始化循环中的所有元素

1
2
3
4
5
int* p = new int[10];
for (int i = 0; i < 10; i++)
{
    p[i] = 0;
}

使用std::memset函数

1
2
int* p = new int[10];
std::memset(p, 0, 10);

使用std::fill_n算法

1
2
int* p = new int[10];
std::fill_n(p, 10, 0);

使用std::vector容器

1
std::vector<int> v(10); // elements zero'ed

如果c++0x可用,使用初始化列表特性

1
2
int a[] = { 1, 2, 3 }; // 3-element static size array
vector<int> v = { 1, 2, 3 }; // 3-element array but vector is resizeable in runtime


如果您正在分配的内存是一个具有可执行某些有用操作的构造函数的类,则new运算符将调用该构造函数并使对象保持初始化状态。

但是,如果您正在分配一个pod或一些没有初始化对象状态的构造函数的东西,那么您就不能在一个操作中使用新的操作符分配内存并初始化该内存。但是,您有几个选项:

1)改用堆栈变量。您可以在一个步骤中分配和默认初始化,如下所示:

1
int vals[100] = {0};  // first element is a matter of style

2)使用memset()。注意,如果您分配的对象不是pod,那么memsetting是一个坏主意。一个特定的例子是,如果您Memset一个类具有虚拟函数,那么您将吹走vtable并使对象处于不可用状态。

3)许多操作系统都有执行所需操作的调用——在堆上分配并初始化数据。一个windows示例是VirtualAlloc()

4)这通常是最好的选择。完全不用自己管理记忆。您可以使用STL容器对原始内存进行任何操作,包括一次性分配和初始化所有内容:

1
std::vector<int> myInts(100, 0);  // creates a vector of 100 ints, all set to zero

是的:

1
std::vector<int> vec(SIZE, 0);

使用矢量而不是动态分配的数组。好处包括不必费心明确地删除数组(当向量超出范围时,它会被删除),而且即使抛出异常,内存也会自动删除。

编辑:为了避免不想阅读下面评论的人进一步推倒选票,我应该更清楚地说,这个答案并不意味着Vector总是正确的答案。但它确实是一种比"手动"更可靠的C++方法来确保删除一个数组。

现在用C++ 11,也有STD::数组,它模拟一个固定大小的数组(VS向量能够增长)。还有std::unique_ptr,用于管理动态分配的数组(可以与此问题的其他答案中回答的初始化相结合)。其中任何一种都比手动处理数组指针更为简单。


std::fill是一种方式。使用两个迭代器和一个值填充区域。或者,for循环,(我想)将是更多的C++方式。

对于将原始整数类型的数组设置为0(具体来说),memset是可以的,尽管它可能会引起注意。也考虑EDCOX1的2度,尽管从C++中使用CAST有点不方便。

就我而言,我几乎总是使用循环。

(我不想再猜测人们的意图,但事实上,std::vector是,所有事物都是平等的,比使用new[]更好。)


您可以始终使用memset:

1
2
int myArray[10];
memset( myArray, 0, 10 * sizeof( int ));


通常,对于项目的动态列表,使用std::vector

通常,我使用memset或循环进行原始内存动态分配,这取决于我预测代码区域将来的变化程度。