I need a container that is able to delete and add elements as fast as possible, without the need of reallocation that usually takes place when we push_back elements in an std::vector
or when we delete elements.
By looking around on the internet I have found that a good way to achieve this is to use a fixed-size container. The class is supplied with a counter which accounts for the number of "active elements". Deletion of an element consists just of swapping said element with the last active one of the container and decreasing the counter of active elements by one.
What do you think of this implementation? How can I improved it?
#include <vector>
template <class Element>
class ObjectPool
{
private:
size_t activeElements;
std::vector<Element> elements;
public:
ObjectPool(size_t maxElements)
{
activeElements = 0;
elements.resize(maxElements);
}
size_t size() const
{
return activeElements;
}
Element& at(size_t index)
{
if (index >= activeElements) {
throw std::out_of_range("System: element requested is not active.");
}
return elements.at(index);
}
const Element& at(size_t index) const
{
if (index >= activeElements) {
throw std::out_of_range("System: element requested is not active.");
}
return elements.at(index);
}
Element& back()
{
if (activeElements <= 0) {
throw std::out_of_range("System: number of active elements is zero.");
}
return elements.at((size_t)(activeElements - 1));
}
const Element& back() const
{
if (activeElements <= 0) {
throw std::out_of_range("System: number of active elements is zero.");
}
return elements.at((size_t)(activeElements - 1));
}
void addBackElement()
{
if (activeElements < elements.size()) {
activeElements++;
}
else
{
throw std::out_of_range("System: maximum limit of elements in the system exceeded.");
}
}
void deleteElement(size_t index)
{
if (index >= activeElements) {
throw std::out_of_range("System: element requested is not active.");
}
activeElements--;
swapElements(activeElements, index);
}
void resize(size_t maxElements)
{
elements.resize(maxElements);
}
private:
void swapElements(size_t i, size_t j)
{
std::swap(elements.at(i), elements.at(j));
}
};
std::deque
,std::unordered_set
orstd::unordered_map
don't fit your use case? \$\endgroup\$