在 C++ 中实现增量数组
Posted
技术标签:
【中文标题】在 C++ 中实现增量数组【英文标题】:Implementing incremental array in C++ 【发布时间】:2012-01-17 13:48:05 【问题描述】:我想实现一个可以随着新值的添加而递增的数组。就像在 Java 中一样。我不知道如何做到这一点。谁能给我一个方法?
这是出于学习目的,因此我不能使用std::vector
。
【问题讨论】:
使用std::vector
,不要重新发明***。 [除非你为了学习而实施它]
是的,即使您将其用于学习,也请在开始之前查看std::vector
的工作原理。
@amit 是的,我这样做是为了学习。谢谢。
@Adembian 我不能使用 std::vector 这是我的 uni 作品。但是谢谢我正在阅读有关矢量的内容。
@JKAUSHALYA:我编辑了问题并添加了您在cmets中提到的信息,如果您认为错误,请回滚或重新编辑。
【参考方案1】:
这是一个起点:您只需要三个变量,nelems
、capacity
和一个指向实际数组的指针。因此,您的课程将开始为
class dyn_array
T *data;
size_t nelems, capacity;
;
其中T
是您要存储的数据类型;为了获得额外的荣誉,请将此作为模板类。现在实现您的教科书或Wikipedia page on dynamic arrays 中讨论的算法。
请注意,new
/delete
分配机制不支持像 C 的 realloc
那样增加数组,因此在增加容量时实际上会移动 data
的内容。
【讨论】:
【参考方案2】:我想借此机会让您对一个有趣但有些困难的话题感兴趣:例外。
如果您自己开始分配内存并随后使用原始指针,您会发现自己处于避免内存泄漏的困境。 即使您将内存的簿记委托给正确的类(例如std::unique_ptr<char[]>
),您仍然必须确保更改对象的操作在失败时使其保持一致状态。
例如,下面是一个简单的类,其中有一个不正确 resize
方法(这是大多数代码的核心):
template <typename T>
class DynamicArray
public:
// Constructor
DynamicArray(): size(0), capacity(0), buffer(0)
// Destructor
~DynamicArray()
if (buffer == 0) return;
for(size_t i = 0; i != size; ++i)
T* t = buffer + i;
t->~T();
free(buffer); // using delete[] would require all objects to be built
private:
size_t size;
size_t capacity;
T* buffer;
;
好的,这就是简单的部分(虽然已经有点棘手了)。
现在,如何在最后推送一个新元素?
template <typename T>
void DynamicArray<T>::resize(size_t n)
// The *easy* case
if (n <= size)
for (; n < size; ++n)
(buffer + n)->~T();
size = n;
return;
// The *hard* case
// new size
size_t const oldsize = size;
size = n;
// new capacity
if (capacity == 0) capacity = 1;
while (capacity < n) capacity *= 2;
// new buffer (copied)
try
T* newbuffer = (T*)malloc(capacity*sizeof(T));
// copy
for (size_t i = 0; i != oldsize; ++i)
new (newbuffer + i) T(*(buffer + i));
free(buffer)
buffer = newbuffer;
catch(...)
free(newbuffer);
throw;
感觉不对?
我的意思是,我们甚至会处理T
的复制构造函数可能引发的异常!是的!
请注意我们遇到的微妙问题:如果抛出异常,我们已更改 size
和 capacity
成员,但仍保留旧的 buffer
。
当然,解决办法很明显:我们应该先改变缓冲区,然后再改变大小和容量。当然……
但要做到这一点“很难”。
我建议使用另一种方法:创建一个不可变数组类(容量应该是不可变的,而不是其余的),并实现一个无异常的 swap
方法。
然后,您将能够更轻松地实现“类事务”语义。
【讨论】:
我刚刚意识到我掩盖了另一个细节:如果抛出异常,也必须正确销毁新复制的元素。【参考方案3】:随着我们添加元素而动态增长的数组称为动态数组、可增长数组,这里是 dynamic array 的完整实现。
【讨论】:
【参考方案4】:在 C 和 C++ 中,数组表示法基本上只是简写的指针数学。 所以在这个例子中。
int fib [] = 1, 1, 2, 3, 5, 8, 13;
这个:
int position5 = fib[5];
和这样说是一回事吗:
int position5 = int(char*(fib)) + (5 * sizeof(int));
所以基本上数组只是指针。
所以如果你想自动分配,你需要编写一些包装函数来调用 malloc() 或 new,(分别是 C 和 C++)。
虽然您可能会发现向量正是您要寻找的...
【讨论】:
以上是关于在 C++ 中实现增量数组的主要内容,如果未能解决你的问题,请参考以下文章