How to implement erase on vector in c++

大憨熊 提交于 2021-02-11 18:15:59

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!