如何在 C++ 中实现矢量的擦除(迭代器擦除(const_iterator 首先,const_iterator 最后))

How can I implements erase( iterator erase(const_iterator first, const_iterator last)) of vector in c++

https://www.cplusplus.com/reference/vector/vector/erase/ 我想在 c++

中创建 vector 的 erase() 方法
 iterator erase(const_iterator position)
    {
        theSize--;
        int index = position - begin();
        
        Object* newObj = new Object[theCapacity];
        for (int i = 0, j = 0; j <= index; ++j)
        
        {
                if (j != index)
                newObj[i++] = objects[j];
        }
        

        std::swap(objects, newObj);
        delete[] newObj;
        

        return &objects[index];
    }

首先,我尝试制作 erase() 并尝试重用它来制作迭代器擦除(const_iterator 首先,const_iterator 最后)

   iterator erase(const_iterator first, const_iterator last)
    {
        int index = last - begin();
        for (auto it = first; it != last; ++it)
        {
            erase(it);
            
        }
        return objects;
       
    }

不知道我的做法对不对。 由于返回值是垃圾值。我认为我的索引是错误的。 我怎样才能改进我的**迭代器擦除(const_iterator位置)**和 我如何重用我的迭代器擦除(const_iterator 位置)来使迭代器擦除(const_iterator 首先,const_iterator 最后)?

v.erase(v.begin(),v.begin()+3)

输入 541234

输出 -842150451-842150451

预计 1234

您不需要重新分配数组;改用移动语义。即使您使用当前的实现,您也可以从旧数组中移动值而不是复制它们中受益。

此外,erase(const_iterator, const_iterator) 接收自己的实现效率更高。

你这里的实际问题是你通过调用 erase 使迭代器无效,正如@UlrichEckhardt 所指出的,即使你没有重新分配数组,你也需要调用 erase with first 而不是 it,因为擦除 it 当前位置的元素会将剩余元素左移一个,导致下一个要擦除的元素放置在当前位置it,不在下一个位置。

这是一个应该有效的简化矢量实现:

template<class T>
class Vector
{
public:
    using iterator = T*;
    using const_iterator = T const*;

    Vector(std::initializer_list<T>&& list)
        : size(list.size()),
        objects(size == 0 ? nullptr : new T[size])
    {
        auto out = objects;
        for (auto& e : list)
        {
            *out = std::move(e);
            ++out;
        }
    }

    ~Vector()
    {
        delete[] objects;
    }

    iterator begin() noexcept
    {
        return objects;
    }

    iterator end() noexcept
    {
        return objects + size;
    }

    const_iterator cbegin() const noexcept
    {
        return objects;
    }

    const_iterator cend() const noexcept
    {
        return objects + size;
    }

    iterator erase(const_iterator pos)
    {
        auto const result = objects + std::distance(cbegin(), pos);
        auto const endIter = end();
        for (auto p = result; p != endIter;)
        {
            auto& lhs = *p;
            ++p;
            lhs = std::move(*p);
        }
        --size;
        return result;
    }

    iterator erase(const_iterator first, const_iterator last)
    {
        auto const result = objects + std::distance(cbegin(), first);
        if (first == last)
        {
            // empty delete sequence
            return result;
        }

        // shift the elements after last
        auto writeIter = result;
        auto readIter = objects + std::distance(cbegin(), last);

        for (auto const endIter = end(); readIter != endIter; ++writeIter, ++readIter)
        {
            *writeIter = std::move(*readIter);
        }
        // remove extra elements from the end
        size = std::distance(objects, writeIter);
        return result;
    }

private:
    size_t size;
    T* objects;
};

int main()
{
    {
        Vector<int> a = { 1, 2, 3, 4, 5 };

        auto iter = a.erase(a.cbegin() + 1, a.cend() - 1);
        std::cout << "element pointed to by returned value: " << *iter << '\n';
        for (auto i : a)
        {
            std::cout << i << '\n';
        }
    }

    {
        Vector<int> a = { 1, 2, 3, 4, 5 };

        auto iter = a.erase(a.cbegin() + 1);
        std::cout << "element pointed to by returned value: " << *iter << '\n';
        for (auto i : a)
        {
            std::cout << i << '\n';
        }
    }
}

注意:成员函数中的循环可以用the overload of std::move taking iterators代替。