我想实现一个可以在添加新值时递增的数组。就像在Java中一样。我不知道该怎么做。谁能给我一个方法?
这是为了学习目的,因此我无法使用std::vector
。
答案 0 :(得分:5)
这是一个起点:您只需要三个变量nelems
,capacity
和指向实际数组的指针。所以,你的课程将从
class dyn_array
{
T *data;
size_t nelems, capacity;
};
其中T
是您要存储的数据类型;为了额外的功劳,请将其设为模板类。现在实现教科书或Wikipedia page on dynamic arrays上讨论的算法。
请注意,new
/ delete
分配机制不支持像C realloc
那样增长数组,因此您实际上将移动data
的内容在增加容量时。
答案 1 :(得分:3)
我想借此机会感兴趣一个有趣但有点困难的话题:例外。
std::unique_ptr<char[]>
),您仍然必须确保更改对象的操作在失败时将其保持一致状态。 / LI>
例如,这是一个简单的类,其中包含不正确的 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
。
修复是显而易见的,当然:我们应该先改变缓冲区,然后再改变大小和容量。当然......
但它很难&#34;做对了。
我建议使用另一种方法:创建一个不可变的数组类(容量应该是不可变的,而不是其余的),并实现一个无异常的swap
方法。
然后,您就可以实现&#34;类似交易的&#34;语义更容易。
答案 2 :(得分:2)
在添加元素时动态增长的数组称为动态数组,可增长数组,这是dynamic array的完整实现。
答案 3 :(得分:0)
在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 ++)。
虽然您可能会发现矢量是您正在寻找的......