C++ 在c+;中拥有一组结构的正确方法是什么+;?

C++ 在c+;中拥有一组结构的正确方法是什么+;?,c++,set,std,C++,Set,Std,我需要有一组自定义结构,以便能够用最小的给定参数快速检索实例。然而,我发现std::set认为某些实例是相同的,尽管它们有不同的值。以下是我的示例程序: #include <set> #include <iostream> struct S { int foo, bar; S(int foo, int bar): foo(foo), bar(bar) {} }; inline bool operator<(const S& a, cons

我需要有一组自定义结构,以便能够用最小的给定参数快速检索实例。然而,我发现std::set认为某些实例是相同的,尽管它们有不同的值。以下是我的示例程序:

#include <set>
#include <iostream>

struct S
{
    int foo, bar;
    S(int foo, int bar): foo(foo), bar(bar) {}
};

inline bool operator<(const S& a, const S& b)
{
    return a.foo < b.foo;
}

int main()
{
    std::set<S> baz;
    baz.emplace(1, 2);
    baz.emplace(1, 3);
    std::cout << baz.size();

    return 0;
}
#包括
#包括
结构
{
int foo,bar;
S(intfoo,intbar):foo(foo),bar(bar){}
};

内联布尔运算符如果
foo
bar
都使
S
唯一,那么您可以修改
运算符这种情况发生,因为您只比较
foo
,如果
foo
相等,则认为对象相等
std::set
只保留一个等效值。如果
bar
使对象唯一,则在比较中包括
bar
,否则,如果仍要保留两个(等效)值,请使用
std::multiset
。两者都是有效的解决方案,具体取决于您想做什么。

您可以尝试使用
std::multiset

不是
std::set
认为
s
的实例是相同的,如果它们具有相同的
foo
,则是您自己的
操作符简化了一点,
std::set
在插入时对两个元素进行两次比较:

  • a
  • b
  • 如果1。如果
    true
    ,则排序时
    a
    b
    之前。
    否则,如果2。如果
    true
    ,则
    b
    a
    之前
    否则(两者都是
    false
    ),
    a
    b
    是等效的


    由于
    S{1,2}
    S{1,3}
    根据您对
    运算符的定义,可能是对其他答案的补充:


    std::set
    保留一个排序集,并使用
    我知道在我们公司,我看到
    memcmp
    用于此目的。但我不知道这是否是“正确”的方法。@AlgirdasPreidžius
    memcmp
    。。。。呃,最好不要。关于填充字节的问题呢?你能详细说明你的问题是什么吗?你几乎是自己回答的。
    S
    实例被认为是等效的,因为比较中不考虑
    bar
    ,并且
    std::set
    不保留等效元素。你到底需要回答什么?到目前为止,您对答案的评论似乎表明,您还有一些其他理由不在比较中包括
    bar
    ,或者使用
    std::multiset
    。请解释这些问题。@DanielJour我刚才说我在现有代码中看到了。如果我没记错的话:它主要是为POD结构完成的。所以我想填充并不是什么大问题。。大多数情况下,..@Yur3k请准确定义“不完全相同”的含义。您是否正在使用
    operator这两种解决方案显然是可行的,但在比较中我不需要使用
    bar
    ,如果我只是将
    bar
    放入其中,编译器可能会对其进行优化。@Yur3k是否要比较
    bar
    ?我不清楚。@Axyxan
    bar
    在这种情况下并不重要。您想要什么样的行为?为什么
    multiset
    不是您正在寻找的解决方案?
    inline bool operator<(const S& a, const S& b)
    {
        if ( a.foo == b.foo )
           return a.bar < b.bar;
        return a.foo < b.foo;
    }