【问题标题】:altering a key for a value in std::map更改 std::map 中值的键
【发布时间】:2013-08-23 01:02:01
【问题描述】:

我需要更改 std::map 中给定值的键。所以我写了这个方法:

bool alter_key(_Kty oldKey, _Kty newKey)
{
    std::map<_Kty, _Ty>::iterator it = this->find(newKey);
    if(it != end()) //can't replace because newKey is already been used.
        return false;

    it = this->find(oldKey);
    if(it == end()) // empty index.
        return false;

    _Ty value = it->second;
    this->erase(it);
    this->insert(std::pair<_Kty, _Ty>(newKey, value));
    return true;
}

它应该可以正常工作,但是可以优化这段代码吗?

【问题讨论】:

  • 您已经分析了您的应用程序并发现这是一个瓶颈?
  • 如果 mapped_type 的复制成本很高,请将其设为 unique/shared_ptr。
  • 是的,它对速度至关重要,但不幸的是我不是一个熟练的 c++ 开发人员。
  • 那么哪一部分是您确定的瓶颈?,地图插入(您什么都不做会使其更快)或对象复制?
  • 如果 _Ty 不是指针,则复制对象。

标签: c++ dictionary map stl key-value


【解决方案1】:

如果您需要加快该特定操作,那么std::map 可能不是容器的正确选择。话虽如此,它也可能是正确的选择,所以下一个问题是该功能有哪些需要优化的地方,该功能的更高成本是多少?是查找吗?创建新元素的成本?

如果更高的成本是数据的复制,那么您可能需要考虑在算法中避免复制。您可以跳过中间副本,而不是从容器复制到局部变量,然后再做一个额外的副本插入到目标中:

insert(std::make_pair(new_key,it->value));
erase(it);

如果value 的复制成本很高但可以移动(右值引用移动,或者默认构造很便宜并且您可以交换内容),您可以利用它:

insert(std::make_pair(new_key,std::move(it->value)));
// alternatively in C++03, for example for large strings or std::vector<> values
value_type& x = *insert(std::make_pair(new_key,ValueType())).first;
swap(x,it->value);

注意事情是如何变得更加复杂和难以理解/维护的。

您可以改进的另一件事是查找。目前,您对容器进行了三次查找:两次确定旧键和新键的存在,第三次插入。你可以减少它。如果您尝试插入并且密钥已经存在,则不会对其进行修改,因此您可以这样做:

using std::swap;
iterator it = find(old_key);
if (it == end()) return false;
std::pair<bool, iterator> ins_res = insert(std::make_pair(new_key,ValueType()));
if (!ins_res.second) return false;
swap(it->second,ins_res.first->second); // swap contents
erase(it);

但是,请考虑 std::map 是否是您的数据结构的正确选择...例如,如果查找成本高且排序不重要,那么 std::unordered_map 可能具有更好的查找性能。

【讨论】:

  • 非常感谢,但对于我的任务,键的唯一性很重要。
  • @user2708147: uniqueness 从未被讨论过,orderuniqueness 不是一回事。 std::mapstd::unordered_map 都提供相同的唯一性保证,只是底层数据结构和复杂性不同。维护数据排序(如std::map)比仅仅保证唯一性更昂贵。
  • 再次感谢您,大卫!我在cplusplus.com 阅读了有关 std::unordered_map 的信息,这正是我所需要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-08
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
  • 2018-04-21
  • 2020-09-12
  • 2017-01-20
相关资源
最近更新 更多