Я хотел бы воспользоваться возможностью, чтобы заинтересовать вас интересной, но довольно сложной темой: исключения.
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
метод исключения меньше.
Тогда вы сможете значительно упростить реализацию «транзакционной» семантики.
использовать 'std :: vector', не изобретать колесо. [если вы не реализуете его для обучения] – amit
Yeap, и даже если вы его реализуете для изучения, изучите, как работает 'std :: vector', прежде чем вы начнете. – sharptooth
@amit Да, я делаю это для обучения. Благодарю. –