Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用动态分配阵列和realloc()实现一些常见ADT_C++_C_Data Structures - Fatal编程技术网

C++ 使用动态分配阵列和realloc()实现一些常见ADT

C++ 使用动态分配阵列和realloc()实现一些常见ADT,c++,c,data-structures,C++,C,Data Structures,当然,每个程序员都听说过,用数组实现堆栈有其缺点,其中大多数是固定大小的;但是在了解了realloc函数之后,似乎有一种方法可以实现这种ADT和其他具有动态变化数组的ADT,如下所示: 首先,我将使用malloc函数动态分配数组的第一个成员。 然后,当我想添加另一个成员时,我所要做的就是realloc大小来增加它,并使用array[n+1]=new item来添加它。 第三,如果我想删除该项,我可以再次使用realloc函数来收缩动态数组 至少从我的角度来看,这些好处是惊人的,因为您将拥有一个堆

当然,每个程序员都听说过,用数组实现堆栈有其缺点,其中大多数是固定大小的;但是在了解了realloc函数之后,似乎有一种方法可以实现这种ADT和其他具有动态变化数组的ADT,如下所示:

首先,我将使用malloc函数动态分配数组的第一个成员。 然后,当我想添加另一个成员时,我所要做的就是realloc大小来增加它,并使用array[n+1]=new item来添加它。 第三,如果我想删除该项,我可以再次使用realloc函数来收缩动态数组

至少从我的角度来看,这些好处是惊人的,因为您将拥有一个堆栈,该堆栈具有动态分配存储和普通阵列的优点,如随机访问和易于操作等

老实说,我真的不相信这是可行的,因为如果是这样的话,为什么我没有在任何教科书或互联网上读到它,我不可能在这里创造出某种发明,因为我实际上还是一个新手


所以一定有什么我没有注意到的错误,我已经准备好去听了:

听起来你想用std::vector作为std::stack类型的基础

vector自动处理大小调整,并动态分配其内容的空间


您应该看看std::stack。我相信std::stack可以为您处理内存分配

听起来您想使用std::vector作为std::stack类型的基础

vector自动处理大小调整,并动态分配其内容的空间


您应该看看std::stack。我相信std::stack可以为您处理内存分配

这只是一个关于是否可能的问题的快速回答:当然可以

C++的库有一个堆栈数据类型,默认情况下,该类型将使用deque作为备份存储,但如果您确实希望使用连续数组来备份堆栈存储,则可以选择使用向量

此外,Sedgewick的算法,第四版书在第1章中讨论了使用数组和动态调整大小来实现堆栈


我敢肯定,在互联网上可以找到无数的实现和讨论。

这只是一个关于是否可能的问题的快速回答:当然可以

C++的库有一个堆栈数据类型,默认情况下,该类型将使用deque作为备份存储,但如果您确实希望使用连续数组来备份堆栈存储,则可以选择使用向量

此外,Sedgewick的算法,第四版书在第1章中讨论了使用数组和动态调整大小来实现堆栈

我敢肯定,在互联网上可以找到无数的实现和讨论。

realloc的一个关键问题是,它可能会也可能不会将现有内存内容移动到新的缓冲区,但如果它确实决定这样做,它将使用字节对字节的拷贝ala memcpy

通常,C++对象是使用移动或复制构造函数来移动或复制的,并且在被释放的内存中的任何对象都应该调用它们的析构函数。MalC/CyrAlc/Fielt函数通常没有任何钩子让调用方管理对象复制,因此C++库使用Realc来存储任意类型的对象的缓冲区是不实际的。 也就是说,realloc可以用于非常简单的对象,memcpy样式的移动是可以接受的。人们确实使用realloc来破解容器类——不过,这样的容器还没有流行到足以进入主要库的程度,这可能是因为它的性能优势比您希望的要小,这取决于realloc能够调整大小的时间比例,例如,vector在调整大小时具有备用容量和内置容量加倍功能,这往往会限制复制成本

realloc的一个关键问题是,它可能会也可能不会将现有内存内容移动到新的缓冲区,但如果它确实决定这样做,它将使用字节对字节的复制ala memcpy来执行

通常,C++对象是使用移动或复制构造函数来移动或复制的,并且在被释放的内存中的任何对象都应该调用它们的析构函数。MalC/CyrAlc/Fielt函数通常没有任何钩子让调用方管理对象复制,因此C++库使用Realc来存储任意类型的对象的缓冲区是不实际的。 也就是说,realloc可以用于非常简单的对象,memcpy样式的移动是可以接受的。人们确实使用realloc来破解容器类——不过,这样的容器还没有流行到足以进入主要库的程度,可能是因为性能优势
s小于您可能希望的值,这取决于realloc可以适当调整大小的时间比例,例如,vector在调整大小时具有备用容量和内置容量翻倍,这往往会限制复制成本

您似乎在询问固定/动态数组或链表结构在堆栈实现方面的区别和缺点

如果您知道堆栈a从未超过某个限制,并且b足够小,不会消耗太多内存,那么固定数组是最简单的方法。内存量取决于具体情况

动态数组允许调整大小并具有O1随机访问,但您必须实现指数调整大小,即使这样,重新分配时的过度复制也可能会影响性能。Realloc有它自己的开销,所以如果在每次插入/删除时调整它的大小,性能可能会很快降低。通常的方案是增长x1.5或x2,收缩到x0.5或更小。堆碎片可能相当高,特别是当大量堆栈同时增长时


当您不需要随机访问并且只对最上面或最近的值进行操作时,链表是一个很好的选择。它允许以较小的堆碎片进行快速插入,因为每个列表节点都很小,大小固定,并且单独分配。OTOH,您有轻微的malloc开销,这在现代分配器中可以忽略。

您似乎在问固定/动态数组或链表结构在堆栈实现方面的区别和缺点

如果您知道堆栈a从未超过某个限制,并且b足够小,不会消耗太多内存,那么固定数组是最简单的方法。内存量取决于具体情况

动态数组允许调整大小并具有O1随机访问,但您必须实现指数调整大小,即使这样,重新分配时的过度复制也可能会影响性能。Realloc有它自己的开销,所以如果在每次插入/删除时调整它的大小,性能可能会很快降低。通常的方案是增长x1.5或x2,收缩到x0.5或更小。堆碎片可能相当高,特别是当大量堆栈同时增长时


当您不需要随机访问并且只对最上面或最近的值进行操作时,链表是一个很好的选择。它允许以较小的堆碎片进行快速插入,因为每个列表节点都很小,大小固定,并且单独分配。OTOH,您有轻微的malloc开销,这在现代分配器中可以忽略不计。

您的想法经过一些调整,已经走上了合理的轨道

通常,您不希望在性能关键区域使用链表表示堆栈,因为分配/释放每个条目的成本以及由此产生的内存碎片可能会增加大量开销,除非您将其与鼓励连续结果的高效固定分配器相结合。即使这样,当配备非常高效的O1固定分配器时,存储小对象列表指针的节点大小的增加也可以大大减少缓存命中率,例如:对于64位系统的32位整数堆栈,我们现在为每个条目添加一个64位指针,并可能为对齐添加额外的结构填充

<> p>但是,每次插入新元素时,也不想支付ReAlLc的成本,如果要用堆栈存储C++对象,使用ReLoCLC是相当笨拙的,因为它可能在新的位置创建新的内存块,并且不调用存储在旧的C++元素中的析构函数以及复制到新块的元素的复制构造函数,除了在VTABLE上进行推送。所以大多数人在C++中不去麻烦RealLc,因为它很不幸缺少与C++对象一起使用的那种类型的信息。 但您确实有一个良好的开端,即高性能堆栈将涉及一个相当连续的结构,以避免链表开销。对您的想法的一个基本调整是,除了堆栈的大小之外,还存储一个额外的积分跟踪容量。当你推到堆栈时,检查大小是否超过容量,如果是,则增加某个因素的容量:将它加倍并分配一个新数组,新容量和传输元素,如果元素不是C++对象,则可以使用RealLoc。
您可以做的另一件事是将链表和数组的思想结合到一个展开链表中,其中每个节点存储K个元素:基本上是链接在一起的数组。通过这种方式,您只需为每K个元素而不是每个元素支付链接开销,并且由于连续性的改善,通常可以获得更好的缓存性能。

您的想法经过一些调整,就走上了合理的轨道

通常,您不希望在性能关键区域使用链表表示堆栈,因为分配/释放每个条目的成本以及由此产生的内存碎片可能会增加很多 开销,除非您将其与鼓励连续结果的高效固定分配器相结合。即使这样,当配备非常高效的O1固定分配器时,存储小对象列表指针的节点大小的增加也可以大大减少缓存命中率,例如:对于64位系统的32位整数堆栈,我们现在为每个条目添加一个64位指针,并可能为对齐添加额外的结构填充

<> p>但是,每次插入新元素时,也不想支付ReAlLc的成本,如果要用堆栈存储C++对象,使用ReLoCLC是相当笨拙的,因为它可能在新的位置创建新的内存块,并且不调用存储在旧的C++元素中的析构函数以及复制到新块的元素的复制构造函数,除了在VTABLE上进行推送。所以大多数人在C++中不去麻烦RealLc,因为它很不幸缺少与C++对象一起使用的那种类型的信息。 但您确实有一个良好的开端,即高性能堆栈将涉及一个相当连续的结构,以避免链表开销。对您的想法的一个基本调整是,除了堆栈的大小之外,还存储一个额外的积分跟踪容量。当你推到堆栈时,检查大小是否超过容量,如果是,则增加某个因素的容量:将它加倍并分配一个新数组,新容量和传输元素,如果元素不是C++对象,则可以使用RealLoc。
您可以做的另一件事是将链表和数组的思想结合到一个展开链表中,其中每个节点存储K个元素:基本上是链接在一起的数组。这样,您只需为每K个元素而不是每个元素的链接开销付费,并且由于连续性的改善,通常可以获得更好的缓存性能。

老实说,我看不出这里有什么问题,至少与编程无关。我的问题是:这种实现真的可以实现吗?还是有什么问题使得它不可能实现?最大的缺点是每次添加新元素时都要重新分配数组。大多数实现都会将数组大小增加2的幂。你说的2的幂是什么意思?你不需要知道进行分析的绝对成本。导致该系统依赖。假设您有一个100万个元素的堆栈,并且每次添加或删除一个元素时,您都会进行realloc。这就是每次一百万个元素的拷贝。当然,大多数人不会那样实现它,但这只是一个折衷考虑的例子。例如,如果堆栈始终很小,那么可能使用固定数组分配就可以了,对于中等大小的堆栈,可能使用动态块大小的realloc,对于超大堆栈,可能使用完整的动态链表。老实说,我看不出这里有什么问题,至少与编程无关。我的问题是:这种实现真的可以实现吗?还是有什么问题使得它不可能实现?最大的缺点是每次添加新元素时都要重新分配数组。大多数实现都会将数组大小增加2的幂。你说的2的幂是什么意思?你不需要知道进行分析的绝对成本。导致该系统依赖。假设您有一个100万个元素的堆栈,并且每次添加或删除一个元素时,您都会进行realloc。这就是每次一百万个元素的拷贝。当然,大多数人不会那样实现它,但这只是一个折衷考虑的例子。例如,如果堆栈总是小的,那么可能使用固定的数组分配就可以了,对于中等大小的堆栈,可能使用动态块大小的realloc,对于超大堆栈,可能使用完整的动态链表。