Add memory reallocation if needed

Not 100% happy with the functions yet, but this works.
This commit is contained in:
karl 2021-03-13 18:09:11 +01:00
parent b0f8a9970f
commit bbb64dd8b7
2 changed files with 50 additions and 6 deletions

View File

@ -78,7 +78,9 @@ class Vector {
} }
void push_back(const T &element) { 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 // Use placement new to directly use pre-allocated memory
new (data + element_count) T(element); new (data + element_count) T(element);
@ -97,7 +99,9 @@ class Vector {
element_count--; 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 // Returns the number of elements in the vector, regardless of the actually
@ -119,10 +123,10 @@ class Vector {
return data[position]; 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) { void reserve(unsigned int addition) {
// TODO: Actual memory allocation
capacity += addition; capacity += addition;
reallocate(capacity);
} }
// Resize the size of the vector to the given new_size // Resize the size of the vector to the given new_size
@ -132,7 +136,10 @@ class Vector {
int difference = new_size - size(); int difference = new_size - size();
if (difference > 0) { if (difference > 0) {
// TODO: Reserve more space if needed if (new_size_exceeds_capacity(new_size)) {
reallocate(new_size);
}
// Add additional default-constructed items // Add additional default-constructed items
for (int i = 0; i < difference; i++) { for (int i = 0; i < difference; i++) {
data[element_count + i] = T(); data[element_count + i] = T();
@ -142,7 +149,10 @@ class Vector {
for (int i = -1; i > difference; i--) { for (int i = -1; i > difference; i--) {
data[element_count + i].~T(); data[element_count + i].~T();
} }
// TODO: Consider deallocating space
if (is_using_excessive_memory()) {
reallocate(get_capacity_for_size(new_size));
}
} }
element_count += difference; element_count += difference;
@ -152,4 +162,29 @@ class Vector {
T *data; T *data;
unsigned int element_count; unsigned int element_count;
unsigned int capacity; 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;
}
}; };

View File

@ -225,5 +225,14 @@ SCENARIO("Resizing a vector", "[vector]") {
REQUIRE(equals); 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);
}
}
} }
} }