我们可以重载push_back()中的std::vector方法以允许非重复元素吗?我知道std::setstd::unordered_set应该避免重复的元素,但是std::set对元素进行排序,而std::unordered_set以不特定的顺序存储元素。我需要按插入顺序检索元素,同时确保不插入重复的元素。

编辑:这个问题可能有重复here。对此副本的最佳解决方案建议具有辅助数据结构和另一个自定义方法“add”。这对我来说不好,因为(我将其放在单独的文档中)在std::vector中插入数据的用户很少引用文档中的任何自定义函数。如果没有有效的方法,这可能是不得已的方法。

最佳答案

许多人建议不要这样做,但是似乎有某种城市传说在绕着这样做,这将导致宇宙经历真空衰减和我们所知道的将溶解的现实。

您可以公开继承自std::vector。但是您必须考虑该怎么做。

如果您继承自vector,强烈建议您不要向其添加任何数据成员。这可能导致对象 slice (谷歌“c++对象 slice ”。)您还需要记住vector没有使用虚函数。这意味着您不能覆盖成员函数。您只能对其进行阴影处理,因此不能保证它将始终是被调用的push_back()函数。例如,如果您将类的对象传递给需要引用vector的对象,则将调用原始对象。

因此,最后,您需要添加一个push_back_unique()函数。但这又意味着可以由一个简单的免费函数代替。因此,不需要继承vector。当然,这意味着永远不能保证 vector 中的元素是唯一的。其他代码可能在某处使用push_back()

如果您要添加全新的便捷功能,而不施加或取消vector的任何限制,则继承vector是有意义的。如果您想要某种看起来像vector的东西,但实际上不是(因为它具有不同的行为和/或限制),则您应该实现自己的类型,通过从其私有(private)继承或拥有它来将容器功能委托(delegate)给vector作为私有(private)数据成员,然后通过公共(public)包装函数复制vector API。

但这实现起来非常繁琐。通常,您实际上并不需要 vector 中的所有API。因此,我想只在vector周围编写一个较小的类,该类仅提供所需的功能。听起来该功能几乎是只读的,因为允许对元素的写访问允许将一个元素设置为与另一个元素相同的值,从而破坏容器的唯一性。因此,您可以执行以下操作:

template<typename T>
class UniqueVector
{
public:
    void push_back(T&& elem)
    {
        if (std::find(vec_.begin(), vec_.end(), elem) == vec_.end()) {
            vec_.push_back(std::forward(elem));
        }
    }

    const T& operator[](size_t index) const
    {
        return vec_[index];
    }

    auto begin() const
    {
        return vec_.cbegin();
    }

    auto end() const
    {
        return vec_.cend();
    }

private:
    std::vector<T> vec_;
};

如果仍然要允许对单个元素进行写访问,则可以提供非const函数,以检查传递的值是否已在 vector 中。喜欢:
void assign_if_unique(size_t index, T&& value)
{
    if (std::find(vec_.begin(), vec_.end(), value) == vec_.end()) {
        vec_[index] = std::forward(value);
    }
}

这是一个最小的例子。您显然应该添加您真正想要的功能。像size()empty()以及您需要的其他任何东西。

关于c++ - 在 vector 中重载push_back()以允许不重复的元素,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57372915/

10-11 22:23
查看更多