C++ std::map 键类必须满足哪些要求才能成为有效键?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6573225/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:22:34  来源:igfitidea点击:

What requirements must std::map key classes meet to be valid keys?

c++stlmapkey

提问by Kian

I want to map objects of a given class to objects of another. The class I want to use as key, however, was not written by me and is a simple structwith a few values. std::map orders it's contents, and I was wondering how it does it, and if any arbitrary class can be used as a key or if there's a set of requirements (operators and what not) that need to be defined.

我想将给定类的对象映射到另一个类的对象。然而,我想用作键的类不是我写的,它是一个简单的struct有几个值的类。std::map 对它的内容进行排序,我想知道它是如何做到的,以及是否可以将任意类用作键,或者是否存在一组需要定义的要求(运算符和什么不是)。

If so, I could create a wrapper for the class implementing the operators map uses. I just need to know what I need to implement first, and none of the references for the class I found onlinespecify them.

如果是这样,我可以为实现运算符映射使用的类创建一个包装器。我只需要知道我需要首先实现什么,并且我在网上找到的类的参考文献都没有指定它们。

采纳答案by James Kanze

All that is required of the key is that it be copiable and assignable. The ordering within the map is defined by the third argument to the template (and the argument to the constructor, if used). This defaultsto std::less<KeyType>, which defaults to the <operator, but there's no requirement to use the defaults. Just write a comparison operator (preferably as a functional object):

密钥所需要的只是它是可复制和可分配的。映射中的排序由模板的第三个参数(以及构造函数的参数,如果使用)定义。这 默认std::less<KeyType>,默认为<运算符,但不要求使用默认值。只需编写一个比较运算符(最好作为功能对象):

struct CmpMyType
{
    bool operator()( MyType const& lhs, MyType const& rhs ) const
    {
        //  ...
    }
};

Note that it must define a strict ordering, i.e. if CmpMyType()( a, b )returns true, then CmpMyType()( b, a )must return false, and if both return false, the elements are considered equal (members of the same equivalence class).

请注意,它必须定义严格的排序,即如果CmpMyType()( a, b )返回真,则CmpMyType()( b, a )必须返回假,如果两者都返回假,则认为元素相等(相同等价类的成员)。

回答by B?ови?

You need to define the operator<, for example like this :

您需要定义 operator<,例如像这样:

struct A
{
  int a;
  std::string b;
};

// Simple but wrong as it does not provide the strict weak ordering.    
// As A(5,"a") and A(5,"b") would be considered equal using this function.
bool operator<(const A& l, const A& r )
{
  return ( l.a < r.a ) && ( l.b < r.b );
}

// Better brute force.
bool operator<(const A& l, const A& r )
{ 
    if ( l.a < r.a )  return true;
    if ( l.a > r.a )  return false;

    // Otherwise a are equal
    if ( l.b < r.b )  return true;
    if ( l.b > r.b )  return false;

    // Otherwise both are equal
    return false;
}

// This can often be seen written as
bool operator<(const A& l, const A& r )
{
   // This is fine for a small number of members.
   // But I prefer the brute force approach when you start to get lots of members.
   return ( l.a < r.a ) ||
          (( l.a == r.a) && ( l.b < r.b ));
}

回答by Nemo

The answer is actually in the reference you link, under the description of the "Compare" template argument.

答案实际上在您链接的参考资料中,在“比较”模板参数的描述下。

The only requirement is that Compare(which defaults to less<Key>, which defaults to using operator<to compare keys) must be a "strict weak ordering".

唯一的要求是Compare(默认为less<Key>,默认为operator<用于比较键)必须是“严格弱排序”。

回答by Kerrek SB

Same as for set: The class must have a strict ordering in the spirit of "less than". Either overload an appropriate operator<, or provide a custom predicate. Any two objects aand bfor which !(a<b) && !(b>a)will be considered equal.

与 for 相同set:本着“小于”的精神,类必须有严格的排序。要么重载适当的operator<,要么提供自定义谓词。任何两个物体a,并b为其!(a<b) && !(b>a)将被视为相等。

The map container will actually keep all the elements in the order provided by that ordering, which is how you can achieve O(log n) lookup and insertion time by key value.

map 容器实际上会按照该排序提供的顺序保留所有元素,这就是您可以通过键值实现 O(log n) 查找和插入时间的方式。