【问题标题】:Operator overloading of C++ STL map with custom classes带有自定义类的 C++ STL 映射的运算符重载
【发布时间】:2017-06-14 04:40:56
【问题描述】:

我对在 C++ 中使用 stl map 有疑问。我知道使用带有自定义类的地图我需要重载“

#include <iostream>
#include <map>
using namespace std;

struct box{
    int e,s,w;
    box(): e(-1), s(-2), w(-3)
    {}

       bool operator< (const box& lhs) const
       {
           return e < lhs.e;
       }

};

int main() {
    // your code goes here
    map<box, int> hashtable;
    box b;
    hashtable[b] = 1;
    return 0;
}

在这里,我非常简单地重载了

bool operator< (const box& lhs) const
{
    return w+s+e < lhs.e+lhs.s+lhs.w;
}

还有其他方法。所以我的问题是,

我在这里唯一的动机是存储成对的 box 和 int(参见 main 函数),以便我可以在 O(log(n)) 时间内访问它们。

更新

我认为拥有一个糟糕的比较器不会影响地图的访问、删除时间,而是会影响地图中存在的键。例如,如果我的比较器是以下

bool operator< (const box& lhs) const
{
    return e < lhs.e;
}

现在假设我将两个元组 (e,s,w) 作为 (1,2,3) 和 (1,3,4)。我想将它插入到上面的地图中。现在因为我有比较器,它仅根据“e”的值来确定,它会拒绝第二个元组。所以最后地图将包含 (1,2,3) 而不是其他元组。

编写比较器的最佳方法是使用std::tie,正如@edgar 在接受的答案中所建议的那样。

bool operator< (const box& lhs) const
{
    return std::tie(e,w,s) < std::tie(lhs.e,lhs.w,lhs.s);
}

这两个元组是不同的,即使元组有不同的顺序。我的问题中有这样的要求。例如 (1,2,3) 与 (2,1,3) 不同。如果我使用以下比较器

bool operator< (const box& lhs) const
{
    return e+w+s < lhs.e+lhs.w+lhs.s;
}

同样只有第一个元组会成功,因为这两个元组的总和相同,所以再次不是一个好的比较器。

【问题讨论】:

  • 仅供参考,std::map 不是哈希表,也不使用哈希。为此,您需要 std::unordered_map。
  • 对于像ews这样的变量名,很难理解operator&lt;对于这个类的含义。
  • @PaulRooney,就我而言,我正在解决盒子堆叠问题。所以它是盒子的长度,呼吸,高度。如果有不同的元组,我想把它们放在树中,这通过 tie 解决。

标签: c++ stl operator-overloading


【解决方案1】:

std::map 不是哈希映射,而是二叉树。

operator&lt; 每次访问树时都会调用,每个查找步骤调用一次。所以很明显,它的复杂性会影响性能(撇开开销不谈,在std::map 中查找的成本与operator&lt; 的成本成正比)。

std::unordered_map 是一个哈希映射。但为此,您需要实现std::hash&lt;box&gt;std::equal_to&lt;box&gt;(散列和相等函子)。在这种情况下不使用operator&lt;

【讨论】:

  • 您能否详细说明“影响性能”的部分...因为在文档中,他们说这是对数时间
  • @paramvir 每次插入、删除或查找都会使用operator&lt; O(ln(n)) 次
【解决方案2】:

所以我的问题是,重载

不,保证搜索、删除和访问元素是在对数时间内执行的。

我的意思是它会影响地图的散列部分。

std::map 不是 std::unordered_map,所以这里没有散列。

如果是这样,重载

我想现在的标准方式是使用std::tie

bool operator<(const box& lhs) const
{
    return std::tie(e, s, w) < std::tie(lhs.e, lhs.s, lhs.w);
}

【讨论】:

  • 感谢 edgar 的回答。所以我的运算符重载方法和您建议的方法不会对树的访问、删除时间产生任何影响......对吗?
  • @paramvir 是的,当然。您可以查看en.cppreference.com/w/cpp/container/map了解所有方法的详细信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 2015-09-27
  • 2012-05-05
相关资源
最近更新 更多