【问题标题】:dynamic array declaration in c++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?

标签: c++ arrays dynamic declaration


【解决方案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::array 和std::vector,我建议使用它而不是手工制作的内存管理(分配new 和delete 或Cs malloc 和free),它没有被释放当引发异常时。如果您需要使用此类函数,则内存管理应始终嵌套在类的构造函数和析构函数中。当对象超出范围时,总是会调用析构函数,因此不会发生内存泄漏。

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

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

【讨论】:

  • alloca 既不是标准 C++ 也不是 C
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2023-02-09
    • 1970-01-01
    • 2015-07-29
    • 2020-08-01
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    • 2014-09-09
    相关资源
    最近更新 更多