如何在 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代替。
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代替。