是否有一个函数可以从向量中删除一个元素而不在 c++ stdlib 中移动它?

Posted

技术标签:

【中文标题】是否有一个函数可以从向量中删除一个元素而不在 c++ stdlib 中移动它?【英文标题】:Is there a function to remove an element from a vector without shifting it in the c++ stdlib? 【发布时间】:2021-04-22 12:08:55 【问题描述】:

如果我使用vector.erase()比如

std::vector<int> n =  3, 5, 6, 7 ;
n.erase(n.begin() + 1);

vector将移除元素后的所有元素向下移动。

C++ 标准库中是否有不会移动元素的函数?就像把后面的元素放在被移除的元素上然后弹回来?

【问题讨论】:

你是如何定义“删除”的? 应该怎么做呢?只是跳过已删除的元素?那么它基本上就是一个链表。您是否正在寻找链表和向量之间的某种混合体? (编辑:听起来我没有彻底阅读这个问题。括号指定了它应该做什么) 不,没有这样的功能,但是好消息是这需要大约两行代码,所以这可以比写这条评论的时间更快。还有这个问题。 不,没有。虽然是自己写的,但它只是一个两行。 在这种情况下,也许您必须考虑 std::vector 是否适合您的数据结构。也许 std::list 在您的应用程序中会更有效。 【参考方案1】:

没有内置任何东西,但自己动手很简单。

std::vector<int> n =  3, 5, 6, 7 ; // create vector
n[1] = std::move(n.back());          // move last element to removal location
n.pop_back();                        // remove unneeded element.

【讨论】:

为什么要交换而不是移动? @lucidbrot OP 在 Q 中确实有 (将后面的元素放在已删除的元素上并弹回)。 @Quentin 因为swap是按照move来实现的。 但是在最后一个元素上加上 5 来删除它是没有用的; n[1] = std::move(n.back()); n.pop_back(); 就足够了。 @Quentin 你的评论对我来说有点太微妙了。代码已更新为执行一次移动而不是交换。【参考方案2】:

如果您不想移动任何元素,那么在 C++20 中,您可以使用 std::optionals 的向量和范围库对此进行建模

#include <cstddef>
#include <optional>
#include <ranges>
#include <vector>

template<typename T>
auto remove_element(std::vector<std::optional<T>> &v, size_t i) 
    v[i] = std::nullopt;

    return v
        | std::views::filter(&std::optional<T>::has_value)
        | std::views::transform([](auto &&o) return *o;);


#include <iostream>

int main() 
    std::vector<std::optional<int>> v1, 2, 3, 4, 5, 6;

    for (int i : remove_element(v, 3))
        cout << i << ','; // 1,2,3,5,6,

    cout << '\n';

【讨论】:

以上是关于是否有一个函数可以从向量中删除一个元素而不在 c++ stdlib 中移动它?的主要内容,如果未能解决你的问题,请参考以下文章

C ++擦除向量末尾的一部分而不重新分配

布隆过滤器

C ++根据成员函数从向量中擦除对象[重复]

C ++在向量迭代中删除并返回指向对象的指针

我想在运算符重载函数中从向量中删除一个元素

在中间插入一个元素到向量中