【问题标题】:Erasing vector::end from vector从向量中擦除向量::end
【发布时间】:2023-03-17 21:35:02
【问题描述】:

当我使用时它是否正常工作(什么都不做)

 vector<T> v;
 v.erase(v.end());

我想使用类似的东西

 v.erase(std::find(...));

我应该if还是v.end()
C++.comCPPreference 上没有关于它的信息

【问题讨论】:

    标签: c++ vector iterator language-lawyer erase


    【解决方案1】:

    标准并没有完全说明,但v.erase(q) 被定义为“擦除q 指向的元素”在[sequence.reqmts] 中。这意味着q 必须实际指向一个元素,而结束迭代器没有。传入 end 迭代器是未定义的行为。

    不幸的是,你需要写:

    auto it = std::find(...);
    if (it != <the part of ... that specifies the end of the range searched>) {
        v.erase(it);
    }
    

    当然,你可以定义:

    template typename<Sequence, Iterator>
    Iterator my_erase(Sequence &s, Iterator it) {
        if (it == s.end()) return it;
        return s.erase(it);
    }
    
    my_erase(v, std::find(v.begin(), v.end(), whatever));
    

    关联容器上的c.erase() 返回void,因此要将这个模板推广到所有容器,您需要一些-&gt; decltype 操作。

    【讨论】:

    • docs 说“擦除除矢量端以外的位置的元素会导致容器重新定位......”。它看起来像将 end() 作为参数。没有任何地方明确表示相反。我不喜欢这个...
    • @Pavel:那你就得和“cplusplus.com”的作者讨论了。它不是 C++ 文档,标准是C++ 文档。但它将position 定义为“指向单个元素的迭代器”。结束迭代器不指向单个元素。
    • @Pavel 他们弄错了。它应该说 end() - 1 而不是“向量结束”。
    【解决方案2】:

    擦除end()(或者就此而言,甚至查看end() 的目标)是未定义的行为。未定义的行为允许有任何行为,包括在您的平台上“正常工作”。这并不意味着您应该这样做。它仍然是未定义的行为,当你以后最不期待的时候,我会以最糟糕的方式来咬你。

    根据您的操作,您可能需要考虑使用setunordered_set,而不是此处的vector

    【讨论】:

    • 谢谢,我知道什么是 UB,我只是想知道,真的是 UB。
    • @RiaD:是的,它是 UB。解决方案很简单,不过,在擦除之前检查一下:{ auto it = v.find(x); if (it != x.end()) { v.erase(it); } }
    • 问题@Billy。出于好奇, end()-1 有效吗?这与 pop_back() 有何不同?
    • @Gaffi:end-1 当且仅当容器不为空时才会起作用。 (同pop_back
    • @KerrekSB,是的,我知道我可以检查,这很容易:D。它只是有些难看,我正在考虑更换它:)
    【解决方案3】:

    你试过了吗?

    v.erase(remove_if(v.begin(), v.end(), (<your criteria>)), v.end());
    

    【讨论】:

    • 缺少其他正确答案并不能使您的答案正确。
    • 我不知道为什么这被否决(除了可能已经编辑的初始答案)。目前的代码是正确的。
    • @DavidRodríguez-dribeas:正如最初发布的那样,它是不正确的。现在它已被编辑为正确,我删除了我的反对票。
    • 我想我不需要remove_if
    • 它会删除所有带有 的元素,而不是首先删除
    猜你喜欢
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    • 2013-02-09
    • 1970-01-01
    相关资源
    最近更新 更多