C++中的动态数组声明

Posted

技术标签:

【中文标题】C++中的动态数组声明【英文标题】:dynamic array declaration in c++ 【发布时间】:2018-03-28 12:00:02 【问题描述】:

我见过两种在 C++ 中声明动态数组的方法。一种是使用 new 运算符:

int *arr = new int [size];

和其他直接声明:

int arr[size];

注意:这里注意 size 是一个变量,其值将由用户在运行时提供。 问题是在 C++ 中声明动态数组的最佳方法是什么?

【问题讨论】:

第二个不是标准C++,它是一个编译器扩展(一些编译器支持) @Gaurav Sahu 有什么问题? 您能具体说明您的问题吗? 第二种语法是有效的 C 但不是 C++。这两件事有不同的含义,C++ 结构被翻译成 C 为 `int* arr = (int*)malloc(sizeof(int) * size)。 C 构造不能直接转换为 C++。 为什么不使用 std::vector-std::array? 【参考方案1】:

假设您的问题是“什么更好?”。

第二种,直接创建数组,在栈上创建数组,第一个在堆上。第二种称为可变长度数组 (VLA),它是非标准 C++ 且不可移植,但在 C 中它是标准的。 GNU C++ 编译器支持这一点,但其他编译器不支持这一点。在内部,数组的分配方式与 alloca(POSIX)/__builtin_alloca(GNU) 一样,它扩展了堆栈帧。 variadic-length-array 可以粉碎你的堆栈(可能会产生一个 SIGSEGV,但也可能会破坏其他数据),而 new-operator 会抛出一个可捕获的异常。 (但是,使用递归函数可以粉碎你的堆栈以​​同样的方式......)。当您知道大小相对较小时,使用 VLA 并不是一个坏习惯。当需要多次分配数组时(VLA 的分配比堆上的分配更快),VLA 甚至可以提高性能。由于 VLA live 在堆栈上,它不需要是 freed/deleted,它会在函数退出时自动释放。 这适用于 GNU 编译器:VLA 确实在销毁时调用析构函数,但分配给 alloca/__builtin_alloca 的内存将在函数结束时释放,因为内存(分配给 malloc)已释放free

作为结论,我认为new 的分配更适合大多数问题。但是 VLA 有利于函数中的本地快速内存分配。没有可移植的方法从函数返回 VLA(无需通过程序集进行破解)(您可以从函数返回具有恒定大小的数组,但需要在签名中指定)。为此,有std::arraystd::vector,我建议使用它而不是手工制作的内存管理(分配newdelete 或Cs mallocfree),它没有被释放当引发异常时。如果您需要使用此类函数,则内存管理应始终嵌套在类的构造函数和析构函数中。当对象超出范围时,总是会调用析构函数,因此不会发生内存泄漏。

你不能用 VLA 和 new/delete 做的一件事是快速调整大小。甚至std::vector 也不使用它。它是通过 C 函数 realloc 完成的,它试图将缓冲区保持在原位。当你需要这个时,你可以轻松地设计一个类似std::vector 的类,它应该在析构函数中调用free。要销毁调用element.~T() 的元素,其中Telement 的类型。

但是std::vector 试图通过分配具有额外空间的缓冲区来提高调整大小的性能。

【讨论】:

alloca 既不是标准 C++ 也不是 C【参考方案2】:

这两种方法的主要区别是第一种从Free-store(Heap)分配内存,第二种从堆栈分配。事实上,第二个不好用,因为堆栈内存与堆相比在空间上非常有限。同样,第一条语句显然返回指向分配内存中第一个元素的指针,而第二条语句返回数组本身。

【讨论】:

以上是关于C++中的动态数组声明的主要内容,如果未能解决你的问题,请参考以下文章

C++之动态数组

无法在 C++ 中声明动态二维数组 [重复]

在c ++中全局声明的动态数组的多个定义[重复]

如何在C++中使用动态三维数组

(C++) 创建可以从函数访问的动态全局数组/向量

堆栈中的动态数组?