Ok, it took a while until I understood the allocators but I think I got it now.
construct seems to be an explicit call to the copy constructor using the already allocated memory. So the construct() call is fine, but the corresponding destruct calls for already used elements which will get overwritten is missing.
I rewrote the code now as follows and my tests seem all to work so far:
Code: Select all
//! Adds an element at the front of the array. If the array is to small to
//! add this new element, the array is made bigger. Please note that this
//! is slow, because the whole array needs to be copied for this.
//! \param element: Element to add at the back of the array.
void push_front(const T& element)
{
if (used + 1 > allocated)
reallocate(used +1);
for (u32 i=used; i>0; --i)
{
//data[i] = data[i-1];
if ( i<used)
allocator.destruct(&data[i]);
allocator.construct(&data[i], data[i-1]);
}
// data[0] = element;
if ( used > 0 )
allocator.destruct(&data[0]);
allocator.construct(&data[0], element);
is_sorted = false;
++used;
}
//! Insert item into array at specified position. Please use this
//! only if you know what you are doing (possible performance loss).
//! The preferred method of adding elements should be push_back().
//! \param element: Element to be inserted
//! \param index: Where position to insert the new element.
void insert(const T& element, u32 index=0)
{
_IRR_DEBUG_BREAK_IF(index>used) // access violation
if (used + 1 > allocated)
reallocate(used +1);
for (u32 i=used; i>index; --i)
{
if ( i<used)
allocator.destruct(&data[i]);
allocator.construct(&data[i], data[i-1]); // data[i] = data[i-1];
}
if ( used > index )
allocator.destruct(&data[index]);
allocator.construct(&data[index], element); // data[index] = element;
is_sorted = false;
++used;
}
(the reason I moved the "used++" out of the loop to the end in the insert function has nothing to do with the bug, but with the fact that this was so confusing otherwise)
edit: When looking on the above code I think it would also not hurt to just call insert(element,0) in push_front. As both are inlined doing that shouldn't cost any performance.