我有std::unordered_map
,我希望两者都增加std::pair
中的第一个值,key
哈希值,并创建对key
的引用。例如:
std::unordered_map<int, std::pair<int, int> > hash;
hash[key].first++;
auto it(hash.find(key));
int& my_ref(it->first);
我可以,而不是使用[]
运算符,使用insert()
插入数据,但我会分配一对,即使它稍后要被解除分配,也会hash
可能已经key
- 不确定。更清楚:
// If "key" is already inserted, the pair(s) will be allocated
// and then deallocated, right?
auto it(hash.insert(std::make_pair(key, std::make_pair(0, 0))));
it->second.first++;
// Here I can have my reference, with extra memory operations,
// but without an extra search in `hash`
int& my_ref(it->first);
我非常倾向于使用第一种选择,但我似乎无法确定哪一种是最好的。有没有更好的解决方案?
P.S。:对我来说理想的解决方案就像插入一样,不需要初始的,可能无用的值分配。
答案 0 :(得分:4)
正如其他人所指出的,“分配”std::pair<int,int>
实际上只不过是复制两个整数(在堆栈上)。对于map<int,pair<int,int>>::value_type
,pair<int const, pair<int, int>>
您处于三int
s,因此使用第二种方法不会产生显着的开销。您可以使用emplace
代替insert
,即:
// Here an `int` and a struct containing two `int`s are passed as arguments (by value)
auto it(hash.emplace(key, std::make_pair(0, 0)).first);
it->second.first++;
// You get your reference, without an extra search in `hash`
// Not sure what "extra memory operations" you worry about
int const& my_ref(it->first);
使用hash[key]
和hash.find(key)
的第一种方法必然会更昂贵,因为元素搜索肯定比迭代器解除引用更昂贵。
当所有参数都只是unordered_map<...>::value_type
时,在构建int
的过程中过早复制参数是一个可以忽略不计的问题。但是,如果您将重量级key_type
或pair
重量级类型设为mapped_type
,则可以使用上述的以下变体尽可能通过引用转发所有内容(并使用)为rvalues移动语义):
// Here key and arguments to construct mapped_type
// are forwarded as tuples of universal references
// There is no copying of key or value nor construction of a pair
// unless a new map element is needed.
auto it(hash.emplace(std::piecewise_construct,
std::forward_as_tuple(key), // one-element tuple
std::forward_as_tuple(0, 0) // args to construct mapped_type
).first);
it->second.first++;
// As in all solutions, get your reference from the iterator we already have
int const& my_ref(it->first);
答案 1 :(得分:1)
这个怎么样:
auto it = hash.find(key);
if (it == hash.end()) { it = hash.emplace(key, std::make_pair(0, 0)).first; }
++it->second.first;
int const & my_ref = it->first; // must be const
(如果是有序地图,您可以使用lower_bound
并提示插入以回收树木漫步。)
答案 2 :(得分:1)
如果我理解正确,你想要的是operator[]
,它会返回iterator
,而不是mapped_type
。 unordered_map
的当前接口不提供此类功能,operator[]
实现依赖于私有成员(至少是boost实现,我在我的环境中没有访问C ++ 11 std文件)。
我认为JoergB的答案会更快,而Kerrek SB的答案会更短。由您来决定对您的项目更重要的是什么。