【问题标题】:What's the easiest way to get Python's `defaultdict` behavior in C++?在 C++ 中获得 Python 的“defaultdict”行为的最简单方法是什么?
【发布时间】:2013-10-21 17:01:33
【问题描述】:

在 Python 中有一个名为defaultdict 的类,它本质上是一个字典,会根据用户在构造时指定的函数按需构造元素。..

C++ 中是否已经存在类似的类,还是我必须通过继承 map 并覆盖 at 方法自己创建它?

【问题讨论】:

  • 看到这个post
  • 我认为最好的方法是创建一个包装std::map(或std::unordered_map)的类。另见stackoverflow.com/questions/922248/…
  • 您是否需要特定的函数来创建元素,或者您是否可以使用默认构造值(例如 0)。在这种情况下,[] 运算符已经这样做了。
  • 我需要一个特定的功能。
  • 你不应该使用继承。只需编写一个为您工作的函数,或者一个 has-a 映射而不是 is-a 映射的类。

标签: c++ python


【解决方案1】:

这不是您问题的直接答案,但如果您想要与 defaultdict 相同的行为进行聚合,如果键不存在,您可以使用 map.emplace 分配默认值,并返回一个迭代器新的或现有的项目(避免第二次查找):

unordered_map<int, size_t> map = {{1, 1}, {2, 3}};
// later...
for (int i = 1; i < 4; i++) {
    auto emplace_pair = map.emplace(i, 0);
    emplace_pair.first->second += 1;
}

【讨论】:

    【解决方案2】:

    标准库中没有任何东西可以完全满足您的需求,您必须自己提供这样的类。

    但是,请注意,从标准库容器(例如std::map)公开继承是一个坏主意;它们不是为此而设计的,它们没有虚拟函数,也没有虚拟析构函数。考虑这个例子,看看为什么这是一个坏主意:

    template <class K, class V, class C, class A>
    void foo(const std::map<K, V, C, A> &arg)
    {
      doSomething(arg.at(K()));
    }
    
    struct MyMap : std::map<int, int>
    {
      int at(int) { return 7; }
    };
    
    int main()
    {
      MyMap m;
      foo(m);  //this will call std::map::at, NOT MyMap::at
    }
    

    相反,让您的班级按价值存储std::map(或者可能是std::unordered_map,以更适合您的实施为准)。或者,如果您认为您可以重用许多标准地图的成员函数并且只覆盖一些,您可以非公开地从它继承并仅发布您需要的函数。示例:

    template <
      class Key,
      class Value,
      class Comparator = typename std::map<Key, Value>::key_compare,
      class Allocator = typename std::map<Key, Value>::allocator_type
    >
    class DefaultDict : private std::map<Key, Value, Comparator, Allocator>
    {
    public:
      // Publish the clear() function as is
      using std::map<Key, Value, Comparator, Allocator>::clear;
    
      // Provide my own at()
      Value& at(const Key &key) {
        return std::map<Key, Value, Comparator, Allocator>::operator[](key); //call the inherited function
      }
    
      // Etc.
    };
    

    【讨论】:

      猜你喜欢
      • 2022-01-24
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      • 2011-12-11
      • 2010-11-17
      • 2010-11-06
      • 2011-03-21
      相关资源
      最近更新 更多