您可以在 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::set
、std::unordered_set
,或者可能是std::map
或std::unordered_map
。这就是你要找的。请参阅您的 C++ 书籍以获取完整说明。
您还问:C++ 编译器肯定有可能在那时动态地进行新分配吗? - 但它确实!
if( data_size <= 1000 ) data = new char[1000]; else if( data_size <= 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++ 中使用“新”模拟动态数组大小吗?的主要内容,如果未能解决你的问题,请参考以下文章