在C ++中获取Python的`defaultdict`行为最简单的方法是什么?

时间:2013-10-14 07:01:53

标签: c++ python

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

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

2 个答案:

答案 0 :(得分:3)

标准库中没有任何内容能够完全符合您的要求,您必须自己提供这样的课程。

但是,请注意,从标准库容器(例如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.
};

答案 1 :(得分:0)

这不是您问题的直接答案,但如果您希望与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;
}
相关问题