您可以在 C++ 中使用“新”模拟动态数组大小吗?

Posted

技术标签:

【中文标题】您可以在 C++ 中使用“新”模拟动态数组大小吗?【英文标题】:Can you mimic dynamic array sizes using 'new' in C++? 【发布时间】:2020-03-30 20:55:22 【问题描述】:

我知道您可以使用 malloc 创建一个动态大小的数组,但我有兴趣使用 new 做同样的事情,部分原因是 malloc 在 C++ 中被认为是不好的做法,主要是出于好奇。

假设我正在编写一个程序,该程序将接收可能多达 MAX_INPUT_SIZE 的字节输入,它太大以至于分配该大小的数组可能会阻碍其他程序在相同的内存。但是,所有输入大小[0, MAX_INPUT_SIZE] 都同样可能被接收。有没有办法编写程序,使堆上的内存分配与输入大小成正比,这样除非收到足够大的输入,否则其他程序的性能不会受到影响?假设这些限制:

无法使用malloc 不能使用 vector 或其他包装器(假设我们正在寻找极快的性能) 解释数据的算法必须在一个数组中包含所有可用数据(出于性能原因,因此仍然可以非常快速地处理小输入) 程序应分配大约等于输入大小的内存

这些限制不切实际地严格,但这只是假设。这是一个潜在的解决方案:

char *data;
long long int data_size;
/* receive input size */

if( data_size <= 1000 )
    data = new char[1000];

else if( data_size <= 10000 )
    data = new char[10000];
...
else if( data_size <= MAX_INPUT_SIZE / 10 )
    data = new char[MAX_INPUT_SIZE / 10];

else if( data_size <= MAX_INPUT_SIZE )
    data = new char[MAX_INPUT_SIZE];

我的问题是,上面的代码实际上只在其代码行运行时分配new 内存,还是为所有new 调用准备内存,然后将指针分配给请求的那个?

本质上,这个程序会在MAX_INPUT_SIZE 超过可用内存但实际data_size 没有的计算机上运行吗?

如果答案是肯定的,它会运行,那么为什么new 会强制您拥有一个在编译时解析的数组大小? C++ 编译器肯定有可能让new 动态分配吗?如果是这样,那么它只是一种设计选择吗?不允许动态数组大小分配的原因是什么?

如果答案是,不,它不会运行,考虑到限制,是否有替代解决方案?

【问题讨论】:

你问:为什么 new 强制你有一个在编译时解析的数组大小 ...但它没有 您正在寻找的是关联容器,例如std::setstd::unordered_set,或者可能是std::mapstd::unordered_map。这就是你要找的。请参阅您的 C++ 书籍以获取完整说明。 您还问:C++ 编译器肯定有可能在那时动态地进行新分配吗? - 但它确实! if( data_size &lt;= 1000 ) data = new char[1000]; else if( data_size &lt;= 10000 ) data = new char[10000]; ??为什么不new char[data_size] 不能使用向量或其他包装器(假设我们正在寻找极快的性能) -- 请测量。让我们看看证明使用vector 会比你想出的任何东西都慢。 【参考方案1】:

上面的代码实际上只在它的代码行运行时分配new 内存,还是为所有new 调用准备内存,然后将指针分配给请求的那个?

直到在运行时实际调用new 后才会分配内存。

本质上,这个程序会在MAX_INPUT_SIZE 超过可用内存但实际data_size 没有的计算机上运行吗?

是的。

为什么new 强制你有一个在编译时解析的数组大小?

它没有。你是从哪里得到这个想法的?只有静态数组需要在编译时指定它们的大小。 动态数组没有。使用new[] 的主要好处之一是您可以为其提供一个直到运行时才知道的值。例如:

char *data;
long long int data_size;
/* receive input size */

data = new char[data_size];

【讨论】:

是的,这可能就是我的想法。如果我改写我的问题来询问关于动态大小的数组声明怎么办?虽然这没有任何意义,但我的解决方案能否模拟动态调整大小? "具有动态大小的数组声明" - 这将是一个所谓的可变长度数组 (VLA),它是非-standard,仅在少数编译器中作为扩展支持。使用动态长度数组的标准方法是使用new[],最好使用std::vector。 “虽然没有意义,但我的解决方案是否可以模拟动态调整大小?” - 我不明白你在问什么。【参考方案2】:

我相信您将数组声明与new 分配混合在一起。

使用数组:

#define this_has_to_be_compile_time_constant  50
// or: const int this_has_to_be_compile_time_constant = 50;
char array[this_has_to_be_compile_time_constant];

但是有了新的:

int this_can_be_a_variable = some_function();
char *array = new char[this_can_be_a_variable];

【讨论】:

是的,这可能就是我的想法。如果我改写我的问题来询问关于动态大小的数组声明怎么办?虽然这毫无意义,但我的解决方案能否模拟动态调整大小? 究竟是什么?什么是“动态调整大小的数组声明”?【参考方案3】:
不能使用向量或其他包装器(假设我们正在寻找 极快的性能)

只需使用矢量。

以下 sn-p 来自运行代码。

游戏板对象的大小在编译时是未知的。

在我的实践中,游戏板是空的,完全不需要时间。

// 创建游戏板 - 使用单元格向量

CellVec_t 游戏板;

因此,在确定大小后,一行会进行分配工作。选项包括默认值、命令行覆盖、显示最大尺寸等。

来自 en.cppreference.com/w/cpp/container/vector:

“就性能而言,重新分配通常是代价高昂的操作。 reserve() 函数可用于消除重新分配,如果 元素是事先知道的。 "

这样

gameBoard.reserve (static_cast<long unsigned int>(aMaxRow * aMaxCol));

GOLUtil_t  gBrd(aMaxRow, aMaxCol, gameBoard, *ansiTerm);

...

调用reserve时gameboard.size()的大小为0,之后容量被完全分配。

【讨论】:

以上是关于您可以在 C++ 中使用“新”模拟动态数组大小吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的可变长度(动态)数组

在 C++ 中动态调整数组的大小

C++简单实现vector

c++中字符串是如何分配内存的?

动态数组 C++,新 Obj[size] 的麻烦只创建 1 个对象指针,而不是数组

CRuntimmeClass 是 C++ 中 malloc 或新方法的等效概念吗