【问题标题】:How to create set of pointers with unique values如何创建具有唯一值的指针集
【发布时间】:2020-10-21 17:05:40
【问题描述】:

假设我有一个定义如下的类

class Foo {
private:
    int date;
    std::string name;

public:
    void setName(std::string a_name){ name = a_name; };
    std::string getName(){ return name; };
    void setDate(int a_date){ date = a_date; }
    int getDate(){ return date; };

    struct FooComparator
    {
        bool operator()(Foo* lhs, Foo* rhs) const { return lhs->getDate() < rhs->getDate(); }
    };
}

现在我想创建几个对象 Foo 并将它们放在按日期排序的集合中,所以我这样做了

std::set<Foo *, Foo::FooComparator> entries;

Foo *a = new Foo();
a->setName("A_OBJ");
a->setDate(10);

entries.insert(a);

Foo *b = new Foo();
b->setName("B_OBJ");
a->setDate(1);

entries.insert(b);

Foo *a_2 = new Foo();
a_2->setName("A_OBJ");
a_2->setDate(9);

entries.insert(a_2);

所以这是问题所在,在我的集合中,我有 3 个条目由 date 排序,因为在指针值上检查了唯一性。有没有办法给set 一个自定义相等比较器,这样它就不会插入a_2,因为已经有一个具有该名称的条目?

我知道unordered_set 可以传递自定义散列函数,但我似乎无法找到类似的方法来使用set,因为我需要条目是唯一的并排序unordered_set不是一个选项。

【问题讨论】:

  • 您的operator() 应该将参数作为常量引用。指针可以指向任何地方,而引用则保证指向一个对象。
  • 更改您的operator() 以比较名称?
  • 您无需动态分配对象即可将它们放入std::set。设置插入操作将插入一个副本。您正在将指针的 副本 插入到您的集合中。在互联网上搜索“内存泄漏”。
  • AFAIK,你想要的只能在无序容器中完成。您必须将其包装在自己的包装器中以提供额外的功能。我不得不问,你有理由使用set&lt;Foo*&gt; 而不是set&lt;Foo&gt;
  • 对于set,唯一性/等价关系和排序关系必须“相同”。这只是(预期)实现为二叉搜索树的结果。如果您的set 是按日期排序的,那么它不会帮助您按名称强制执行唯一性(除了,正如@Eljay 指出的那样,让您遍历所有Foos 以查看在插入之前是否使用了名称)。如果您需要快速的名称唯一性检查,也许可以尝试使用两个sets,一个名称和一个Foos(按日期排序),您可以在插入之前/插入时检查/更新前者后者?

标签: c++ set unique


【解决方案1】:

对于集合,ab 的相等性定义为 !(a &lt; b) &amp;&amp; !(b &lt; a)。您应该更改比较器功能以反映这一点:

bool operator()(Foo* lhs, Foo* rhs) const {
    if (lhs->getName() == rhs->getName()) {
        return false;
    }
    return lhs->getDate() < rhs->getDate();
}

【讨论】:

  • 这是不允许的。例如。我们得到("A", 5) &lt; ("B", 6)("B", 6) &lt; ("A", 7),这应该给我们("A", 5) &lt; ("A", 7),但这并不成立。因此,这个“排序”是无效的,不是std::set 的有效参数,并且在这样使用时会导致 UB。在操作上,根本没有办法实现 std::set 以便可以在比较中对 OP 所需的行为进行编码,并且该集合仍然具有它指定具有的所有好的 O(log n) 属性。
  • 我们开始吧:甚至打折 UB,using a comparator like this simply doesn't work
猜你喜欢
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 2018-12-02
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多