diff --git a/Vector.h b/Vector.h index 0f391ae..1ea8a38 100644 --- a/Vector.h +++ b/Vector.h @@ -78,7 +78,9 @@ class Vector { } void push_back(const T &element) { - // TODO: Allocate additional space if needed + if (new_size_exceeds_capacity(size() + 1)) { + reallocate(get_capacity_for_size(size() + 1)); + } // Use placement new to directly use pre-allocated memory new (data + element_count) T(element); @@ -97,7 +99,9 @@ class Vector { element_count--; - // TODO: Consider deallocating memory if a certain threshold was reached + if (is_using_excessive_memory()) { + reallocate(get_capacity_for_size(size())); + } } // Returns the number of elements in the vector, regardless of the actually @@ -119,10 +123,10 @@ class Vector { return data[position]; } - // Expand the capacity of the vector by the given addition + // Expand the capacity of the vector by at least the given addition void reserve(unsigned int addition) { - // TODO: Actual memory allocation capacity += addition; + reallocate(capacity); } // Resize the size of the vector to the given new_size @@ -132,7 +136,10 @@ class Vector { int difference = new_size - size(); if (difference > 0) { - // TODO: Reserve more space if needed + if (new_size_exceeds_capacity(new_size)) { + reallocate(new_size); + } + // Add additional default-constructed items for (int i = 0; i < difference; i++) { data[element_count + i] = T(); @@ -142,7 +149,10 @@ class Vector { for (int i = -1; i > difference; i--) { data[element_count + i].~T(); } - // TODO: Consider deallocating space + + if (is_using_excessive_memory()) { + reallocate(get_capacity_for_size(new_size)); + } } element_count += difference; @@ -152,4 +162,29 @@ class Vector { T *data; unsigned int element_count; unsigned int capacity; + + bool is_using_excessive_memory() { + return 10 + element_count * 2 < capacity; + } + + bool new_size_exceeds_capacity(unsigned int new_size) { + return new_size > capacity; + } + + // Allocate enough memory to hold at least new_size entries. + // Note that this function doesn't validate its input for optimization + // reasons! + void reallocate(unsigned int new_size) { + T *new_data = new T[new_size]; + std::copy(data, data + element_count, new_data); + delete[] data; + + data = new_data; + } + + // Return a sensible capacity for the given size (including some + // padding). + unsigned int get_capacity_for_size(unsigned int size) { + return size * 2 + 5; + } }; diff --git a/test.cpp b/test.cpp index a39bd2b..87e69e4 100644 --- a/test.cpp +++ b/test.cpp @@ -225,5 +225,14 @@ SCENARIO("Resizing a vector", "[vector]") { REQUIRE(equals); } } + + WHEN("Resizing to 100") { + v.resize(100); + + THEN("All 100 items should be accessible and modifyable") { + REQUIRE_NOTHROW(v[0] = 10.0); + REQUIRE_NOTHROW(v[99] = 10.0); + } + } } }