通过指针擦除 STL 向量

Posted

技术标签:

【中文标题】通过指针擦除 STL 向量【英文标题】:STL vector erase via pointer 【发布时间】:2017-09-11 11:43:15 【问题描述】:

我 understand (at least I think I do) 指出指针可以用作随机 STL 迭代器。

为什么除非我将指针转换为迭代器,否则以下代码无法编译?

vector<int> v1, 2, 3;
v.erase(&v[0]);

【问题讨论】:

为什么你认为指向元素的指针和迭代器是一样的(std::vector&lt;int&gt;::iterator)? 你得到什么错误? 虽然可以使用指针实现迭代器,但指针不会自动成为迭代器。 指针是迭代器,但不一定是vector的迭代器,即std::vector&lt;...&gt;::iterator 已经有一些实现可以做到这一点,VC6 可能就是其中之一。 iterator 类型允许 是一个指针,但也可以是一个类。然后你的代码就不起作用了。 【参考方案1】:

您可以将指针传递给算法,例如std::sortstd::findstd::copy。这些模板可配置为可用作适当迭代器的任何内容。

这并不意味着不同的迭代器一定会相互转换。

std::vector&lt;int&gt; 容器的方法erase 只能与迭代器一起使用相同向量的元素。正如已经指出的那样,这可以实现为指针,但通常不是,原因如下: C++ std::vector<>::iterator is not a pointer, why?

考虑std::find

template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );

这里InputIt是一个模板参数。模板std::find 将适用于满足input iterator 要求的任何迭代器类型,并且其operator* 返回的内容可以与类型T 进行比较。指针在这里工作得很好。正如 Fire Lancer 在评论中正确指出的那样,firstlast 都必须是 InputIt 类型。

现在将此与std::vector::erase进行比较:

iterator erase( const_iterator pos );

这需要一个const_iterator,它是std::vector 类的类型定义之一。这是一种特定类型的迭代器,而不是模板参数。

【讨论】:

pairs 指针传递给这些算法实际上是一种随机访问迭代器类型。但是,您仍然不能将指针和向量迭代器作为“对”传递给它们,即使指针在向量内。【参考方案2】:

vector.erase(...)的定义是

iterator erase( const_iterator pos );

const iterator 本身就是一个类。 因此,如果有一个指向这个类的普通指针的转换,那么就可以做到这一点。但我认为没有。

但一件事是在需要迭代器的地方使用它,另一件事是在算法中使用。

如果需要iterator,则只能使用迭代器。

在算法中,iterator 不是预期的。只有满足iterator 的Concept 的对象(通常是beginend 返回所需的迭代器/指针)。

【讨论】:

算法需要迭代器,而不是“开始/结束的对象......”。 算法使用模板——参数不是iterator的具体类型。您可以将任何满足 iterator 概念的对象传递给函数。【参考方案3】:

虽然指针是迭代器,但它们与 vector 迭代器的 type 不同(至少它们不必是)。

您可以像这样使用迭代器和指针算法将指向向量元素的指针转换为迭代器。

std::vector<int> v1, 2, 3;

int* p = &v[0]; // a pointer

auto v_iter = v.begin() + std::distance(v.data(), p); // an equivalent vector::iterator

v.erase(v_iter);

这仅适用于std::vectorstd::array 等连续容器。

【讨论】:

以上是关于通过指针擦除 STL 向量的主要内容,如果未能解决你的问题,请参考以下文章

从向量中擦除指针

对于向量中的指针,我们应该在擦除之前还是之后删除?

STL————vector的用法

如何在 STL 中使用指向向量的指针,就像我们在将数组地址传递给另一个函数时将指针分配给数组一样?

C++:问题向量 STL

是否需要清除 STL 向量