如何用C ++中的new运算符初始化内存?

时间:2010-02-05 00:06:20

标签: c++ initialization memory-management new-operator

我刚刚开始进入C ++,我想养成一些好习惯。如果我刚刚使用int运算符分配了new类型的数组,那么如何将它们全部初始化为0而不自行循环遍历它们?我应该使用memset吗?是否有“C ++”方法可以做到这一点?

10 个答案:

答案 0 :(得分:342)

这是一个令人惊讶的鲜为人知的C ++特性(事实证明,没有人将此作为答案),但它实际上有默认初始化数组的特殊语法(从技术上讲,它被称为标准中的“价值初始化”:

new int[10]();

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

ISO C ++ 03 5.3.4 [expr.new] / 15明确允许这样做:

  

创建类型为T的对象的new-expression初始化该对象,如下所示:

     

...

     
      
  • 如果new-initializer的格式为(),则该项值已初始化(8.5);
  •   

并不限制允许使用此类型的类型,而(expression-list)表单则由同一部分中的其他规则明确限制,以使其不允许数组类型。

答案 1 :(得分:24)

假设你真的想要一个数组而不是std :: vector,那么“C ++方式”就是这个

#include <algorithm> 

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

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

但请注意,在实际应用中,这实际上只是一个将每个元素分配给0的循环(实际上没有其他方法可以做到这一点,除非有特殊架构支持硬件级别)。

答案 2 :(得分:20)

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

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

int* p = new int[10];
for (int i = 0; i < 10; i++)
{
    p[i] = 0;
}

使用<cstring>

中的std::memset功能
int* p = new int[10];
std::memset(p, 0, 10);

使用<algorithm>

中的std::fill_n算法
int* p = new int[10];
std::fill_n(p, 10, 0);

使用std::vector容器

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

如果C++0x可用,请使用initializer list功能

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

答案 3 :(得分:7)

如果你要分配的内存是一个带有构造函数的类,它会执行一些有用的操作,new new将调用该构造函数并保持对象的初始化。

但是如果你正在分配一个POD或没有构造函数初始化对象状态的东西,那么就不能在一次操作中分配内存并用operator new初始化那个内存。但是,您有几种选择:

1)改为使用堆栈变量。您可以一步分配和default-initialize,如下所示:

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

2)使用memset()。请注意,如果您要分配的对象不是POD,则设置它是一个坏主意。一个具体的例子是,如果你设置一个具有虚函数的类,你将吹掉vtable并使你的对象处于不可用的状态。

3)许多操作系统都有调用你想要的东西 - 在堆上分配并将数据初始化为某些东西。 Windows示例为VirtualAlloc()

4)这通常是最好的选择。避免必须自己管理内存。您可以使用STL容器执行您对原始内存所做的任何事情,包括一次性分配和初始化:

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

答案 4 :(得分:6)

是的,有:

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

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

编辑:为了避免那些不愿意阅读下面评论的人进一步推销,我应该更清楚地说明这个答案并没有说矢量总是正确的答案。但它肯定是一种比“手动”确保删除数组更多的C ++方式。

现在使用C ++ 11,还有std :: array模拟一个恒定大小的数组(vs能够增长的向量)。还有std :: unique_ptr管理一个动态分配的数组(可以与初始化结合,如在这个问题的其他答案中回答的那样)。其中任何一种都比手动处理指向数组的指针更加C ++方式,恕我直言。

答案 5 :(得分:2)

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

具体来说,为了将原始整数类型的数组设置为0,memset很好,尽管它可能会引起人们的注意。还要考虑calloc,尽管由于演员而使用C ++有点不方便。

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

(我不想第二次猜测人们的意图,但std::vector确实是,所有条件都相同,优于使用new[]。)

答案 6 :(得分:1)

你总是可以使用memset:

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

答案 7 :(得分:0)

对于 c++,使用 std::array<int/*type*/, 10/*size*/> 而不是 c 样式数组。这在 c++11 标准中可用,这是一个很好的做法。有关标准和示例,请参见 here。如果您出于某些原因想坚持使用旧的 c 样式数组,有两种可能的方法:

  1. int *a = new int[5](); 此处将括号留空,否则会出现编译错误。这将初始化分配数组中的所有元素。这里如果不使用括号,它仍然会用零初始化整数值,因为 new 将调用构造函数,在本例中为 int()
  2. int *a = new int[5] {0, 0, 0}; 这在 c++11 标准中是允许的。在这里,您可以使用您想要的任何值初始化数组元素。在这里确保您的初始化列表({} 中的值)大小不应大于您的数组大小。小于数组大小的初始化列表大小没问题。数组中剩余的值将被初始化为 0。

答案 8 :(得分:0)

初始化普通动态数组的可能方法。根据您的要求选择一个。

int* x = new int[5];          // gv gv gv gv gv (gv - garbage value)
int* x = new int[5]();        // 0  0  0  0  0 
int* x = new int[5]{};        // 0  0  0  0  0  (Modern C++)
int* x = new int[5]{1,2,3};   // 1  2  3  0  0  (Modern C++)

答案 9 :(得分:-1)

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

通常我使用memset或循环来进行原始内存动态分配,具体取决于我预期将来代码区域的变量。