C++ std::map 默认值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2333728/
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
std::map default value
提问by anon
Is there a way to specify the default value std::map
's operator[]
returns when an key does not exist?
当键不存在时,有没有办法指定默认值std::map
的operator[]
返回值?
采纳答案by anon
No, there isn't. The simplest solution is to write your own free template function to do this. Something like:
不,没有。最简单的解决方案是编写您自己的免费模板函数来执行此操作。就像是:
#include <string>
#include <map>
using namespace std;
template <typename K, typename V>
V GetWithDef(const std::map <K,V> & m, const K & key, const V & defval ) {
typename std::map<K,V>::const_iterator it = m.find( key );
if ( it == m.end() ) {
return defval;
}
else {
return it->second;
}
}
int main() {
map <string,int> x;
...
int i = GetWithDef( x, string("foo"), 42 );
}
C++11 Update
C++11 更新
Purpose: Account for generic associative containers, as well as optional comparator and allocator parameters.
目的:考虑通用关联容器,以及可选的比较器和分配器参数。
template <template<class,class,class...> class C, typename K, typename V, typename... Args>
V GetWithDef(const C<K,V,Args...>& m, K const& key, const V & defval)
{
typename C<K,V,Args...>::const_iterator it = m.find( key );
if (it == m.end())
return defval;
return it->second;
}
回答by SurvivalMachine
While this does not exactly answer the question, I have circumvented the problem with code like this:
虽然这并不能完全回答这个问题,但我已经用这样的代码规避了这个问题:
struct IntDefaultedToMinusOne
{
int i = -1;
};
std::map<std::string, IntDefaultedToMinusOne > mymap;
回答by Mike Seymour
The C++ standard (23.3.1.2) specifies that the newly inserted value is default constructed, so map
itself doesn't provide a way of doing it. Your choices are:
C++ 标准 (23.3.1.2) 指定新插入的值是默认构造的,因此map
它本身没有提供这样做的方法。您的选择是:
- Give the value type a default constructor that initialises it to the value you want, or
- Wrap the map in your own class that provides a default value and implements
operator[]
to insert that default.
- 给值类型一个默认构造函数,将它初始化为你想要的值,或者
- 将地图包装在您自己的类中,该类提供默认值并实现
operator[]
插入该默认值。
回答by jyw
More General Version, Support C++98/03 and More Containers
更通用的版本,支持C++98/03及更多容器
Works with generic associative containers, the only template parameter is the container type itself.
适用于通用关联容器,唯一的模板参数是容器类型本身。
Supported containers: std::map
, std::multimap
, std::unordered_map
, std::unordered_multimap
, wxHashMap
, QMap
, QMultiMap
, QHash
, QMultiHash
, etc.
支持的容器:std::map
,std::multimap
,std::unordered_map
,std::unordered_multimap
,wxHashMap
,QMap
,QMultiMap
,QHash
,QMultiHash
,等。
template<typename MAP>
const typename MAP::mapped_type& get_with_default(const MAP& m,
const typename MAP::key_type& key,
const typename MAP::mapped_type& defval)
{
typename MAP::const_iterator it = m.find(key);
if (it == m.end())
return defval;
return it->second;
}
Usage:
用法:
std::map<int, std::string> t;
t[1] = "one";
string s = get_with_default(t, 2, "unknown");
Here is a similar implementation by using a wrapper class, which is more similar to the method get()
of dict
type in Python: https://github.com/hltj/wxMEdit/blob/master/src/xm/xm_utils.hpp
下面是使用包装类的类似实现,它更类似于Python 中get()
的dict
type方法:https: //github.com/hltj/wxMEdit/blob/master/src/xm/xm_utils.hpp
template<typename MAP>
struct map_wrapper
{
typedef typename MAP::key_type K;
typedef typename MAP::mapped_type V;
typedef typename MAP::const_iterator CIT;
map_wrapper(const MAP& m) :m_map(m) {}
const V& get(const K& key, const V& default_val) const
{
CIT it = m_map.find(key);
if (it == m_map.end())
return default_val;
return it->second;
}
private:
const MAP& m_map;
};
template<typename MAP>
map_wrapper<MAP> wrap_map(const MAP& m)
{
return map_wrapper<MAP>(m);
}
Usage:
用法:
std::map<int, std::string> t;
t[1] = "one";
string s = wrap_map(t).get(2, "unknown");
回答by Ben
C++17 provides try_emplace
which does exactly this. It takes a key and an argument list for the value constructor and returns a pair: an iterator
and a bool
.: http://en.cppreference.com/w/cpp/container/map/try_emplace
C++17 提供了try_emplace
这正是这样做的。它接受值构造函数的键和参数列表,并返回一对:aniterator
和 a bool
.: http://en.cppreference.com/w/cpp/container/map/try_emplace
回答by Thomas Eding
template<typename T, T X>
struct Default {
Default () : val(T(X)) {}
Default (T const & val) : val(val) {}
operator T & () { return val; }
operator T const & () const { return val; }
T val;
};
<...>
std::map<KeyType, Default<ValueType, DefaultValue> > mapping;
回答by Michael Anderson
There is no way to specify the default value - it is always value constructed by the default (zero parameter constructor).
无法指定默认值 - 它始终是由默认值(零参数构造函数)构造的值。
In fact operator[]
probably does more than you expect as if a value does not exist for the given key in the map it will insert a new one with the value from the default constructor.
事实上,operator[]
可能比您预期的要多,就好像映射中给定键的值不存在一样,它会插入一个具有默认构造函数值的新值。
回答by the swine
The value is initialized using the default constructor, as the other answers say. However, it is useful to add that in case of simple types (integral types such as int, float, pointer or POD (plan old data) types), the values are zero-initialized (or zeroed by value-initialization (which is effectively the same thing), depending on which version of C++ is used).
正如其他答案所说,该值是使用默认构造函数初始化的。但是,在简单类型(整数类型,如 int、float、指针或 POD(计划旧数据)类型)的情况下,添加值是有用的,这些值是零初始化的(或通过值初始化为零(这实际上是同样的事情),具体取决于使用的 C++ 版本)。
Anyway, the bottomline is, that maps with simple types will zero-initialize the new items automatically. So in some cases, there is no need to worry about explicitly specifying the default initial value.
无论如何,底线是,具有简单类型的映射将自动对新项目进行零初始化。所以在某些情况下,无需担心显式指定默认初始值。
std::map<int, char*> map;
typedef char *P;
char *p = map[123],
*p1 = P(); // map uses the same construct inside, causes zero-initialization
assert(!p && !p1); // both will be 0
See Do the parentheses after the type name make a difference with new?for more details on the matter.
请参阅类型名称后的括号是否与 new 有所不同?有关此事的更多详细信息。
回答by Dean
One workaround is to use map::at()
instead of []
.
If a key does not exist, at
throws an exception.
Even nicer, this also works for vectors, and is thus suited for generic programming where you may swap the map with a vector.
一种解决方法是使用map::at()
而不是[]
. 如果键不存在,则at
抛出异常。更好的是,这也适用于向量,因此适用于泛型编程,您可以将映射与向量交换。
Using a custom value for unregistered key may be dangerous since that custom value (like -1) may be processed further down in the code. With exceptions, it's easier to spot bugs.
对未注册的键使用自定义值可能很危险,因为该自定义值(如 -1)可能会在代码中进一步处理。除了例外,更容易发现错误。
回答by VDVLeon
Maybe you can give a custom allocator who allocate with a default value you want.
也许您可以提供一个自定义分配器,该分配器使用您想要的默认值进行分配。
template < class Key, class T, class Compare = less<Key>,
class Allocator = allocator<pair<const Key,T> > > class map;