拥有:
std::map<const std::string,A > cache;
如何插入此容器(可以重复尝试):
cache.insert(std::make_pair(id,ps));
cache.insert(std::pair<std::string,A>(id,ps));
if(cache.find(id) == cache.end()){
cache[id] = ps;
}
为什么??(就时间和记忆而言)
你有更好的解决方案吗?
更新: 我没有使用C ++ 11
更新-2: 好的,到目前为止我们意识到:
make_pair
和pair<>
类似。
insert
和[ ]
(有或没有if
检查)都会调用copy
。那么......之间的竞争是:
insert
[ ]
(具有if
检查)[ ]
(if
检查并swap)你更喜欢哪一个?
再次感谢
答案 0 :(得分:6)
我建议emplace
:
template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );
// usage:
cache.emplace(id, ps);
但是,这取决于你是否想要第二次插入
失败(如上所述,返回std::pair<iterator,bool>
,其中.second
表示插入成功或失败 - 如果您不在乎,可以忽略它,作为失败的唯一原因是现有密钥)或
覆盖现有值(最简单且通常完全足以编写cache[id] = ps;
,但如果要避免构造元素对的默认构造,则可以使用find
然后根据需要覆盖现有或emplace
新元素。
有时您可能会考虑将一个或两个参数标记为可移动的(即,您不关心emplace
返回后局部变量留在哪个(有效)状态,这可能允许额外的优化)。您可以从上面的原型中看到,使用&&
接受了参数,这暗示了执行此类优化的能力。
cache.emplace(std::move(id), std::move(ps));
答案 1 :(得分:5)
第三个在时间上明显较差,因为它在实际插入时要求地图中的两个查找(一个用于find()
,一个用于[]
)。所以坚持使用insert()
函数。
现在的问题是:std::make_pair()
或std::pair<A, B>()
?遵循DRY的原则通常是个好主意,这意味着您不应该重复这些类型,因此请使用std::make_pair()
。
如果你有C ++ 11,最好的选择是使用emplace()
:
cache.emplace(id, ps);
作为旁注,将地图键入std::map<const std::string, A>
毫无意义。地图中的键已经不可变;它只是使用std::map<std::string, A>
更简洁(并且不会产生WTF时刻),而且你很难找到这两者不同的情况。
答案 2 :(得分:4)
cache.insert(std::make_pair(id,ps));
这将复制id
和ps
。如果他们有“重型”拷贝构造器,这将浪费一些时间和内存。
cache.insert(std::pair<std::string,A>(id,ps));
它确实类似于make_pair
if(cache.find(id) == cache.end()){
cache[id] = ps;
}
最好不经检查使用:cache[id] = ps;
。但是,在第一个元素插入时,将构造类型为decltype(ps)
的“默认”对象。然后,将其分配(使用operator=
)到ps
。如果它很重,这也可能是个问题。但是,如果 swap 方法不可用,我认为它是首选方式。
cache.emplace(id, ps);
这可能看起来像零拷贝安置,但事实并非如此。 emplace
接收构造函数参数,因此将调用默认的复制构造函数。它的C ++ 11。
我认为最有效的方法是
cache[id].swap(ps);
这应该是最少量的副本,但缺点是您的ps
将被重置(或包含旧值)。