问题
Learning from Accelerated C++: Practical Programming by Example, in chapter 11, there was an implementation (only with basic features) of vector container from STL. After that was an exercise for implementing erase function just as std::vector does. What I have tried:
#include <memory>
template<class T>
class Vec{
private:
T *data;
T *avail;
T *limit;
std::allocator<T> alloc;
...
public:
explicit Vec(size_t n, const T &val = T())
{
create(n, val);
}
T *const begin()
{
return data;
}
T *const end()
{
return avail;
}
T *erase(T* const pos);
...
};
template <class T>
void Vec<T>::create(size_t n, const T &val)
{
data = alloc.allocate(n);
limit = avail = data + n;
std::uninitialized_fill(data, limit, val);
}
// here I am trying to implement the erase function with 3 pointers (data, avail, limit)
template<class T>
T* Vec<T>::erase(T *const i)
{
if(i==end())
{
return end();
}
else if(i >= begin() && i < end())
{
size_t member = i-data;
size_t size = limit-data;
T* new_data = alloc.allocate(size);
std::uninitialized_copy(data, i, new_data);
T* new_avail = std::uninitialized_copy(i+1, avail, i);
data = new_data;
avail = new_avail;
limit = data + size;
return &data[member];
}
else
{
return 0;
}
}
Now If I want to check, if that function works correctly:
#include "vec.hpp"
int main()
{
Vec<int> v(5, 2);
if (v.erase(v.begin()+2))
{
for (int i:v)
{
cout << i << endl;
}
}
}
I get
...
0
0
0
0
Segmentation fault
I have somehow made infinity allocation-loop, but I have no idea how. Anyway, How can I make the erase function (or in another words, how to shift elements after the erased one to left), via std::uninitialized_copy?
EDIT: the whole class definition is there:
https://www.codepile.net/pile/rLmz8wRq
回答1:
Here you create new storage for vector:
T* new_data = alloc.allocate(size);
and here you write to array pointed by argument, which (supposedly) points to location on old storage. new_avail would point to old storage.
T* new_avail = std::uninitialized_copy(i+1, avail, i);
^ that's destination
^ that's source
Then you even leak memory:
data = new_data; // old storage pointed by data is lost along with the "tail" of array
After this vector state is completely broken, pointer arithmetic go to undefined area:
avail = new_avail; // avail points to old storage, data points to new one.
// (data < avail) no longer guaranteed to be true
Because in all likelihood data would be greater than avail, you don't get an infinite loop, you may get a very long one. OR may not. Attempt to iterate through vector after this "erase" amounts to Undefined Behavior.
来源:https://stackoverflow.com/questions/63331622/how-to-implement-erase-on-vector-in-c