【问题标题】:gnu C++ hash_map: erasing a key: defined?gnu C++ hash_map:擦除一个键:定义?
【发布时间】:2013-09-13 17:07:08
【问题描述】:

考虑以下程序,这是一个尝试重现某些遗留代码问题的最小示例:

#include <iostream>
#include <ext/hash_map>

// Define a hash for std::string class so we can use it as keys
// in hash_map below.
namespace __gnu_cxx {
    template <>
        struct hash<std::string> {
            size_t operator() (const std::string& x) const {
                return hash<const char*>()(x.c_str());
            }
        };
}

// Data class contains a string
class Data {
    public:
        std::string s;
        Data() { s = "foobar"; }
        Data(std::string s_) : s(s_) {}
};

// Map keyed by string.  Values are Data instances
typedef __gnu_cxx::hash_map<std::string, Data> DataMap;

int main()
{
    DataMap m;
    std::string key = "test";

    // I am storing a "Data" instance d, for "key".  d.s is the same as key.
    Data d = Data(key);
    m[key] = d;

    DataMap::iterator it = m.find(key);
    if (it == m.end()) {
        std::cerr << "not there " << std::endl;
        return 1;
    }
    Data *dp = &it->second;
    // Question about the following line.  Is the behavior well-defined?
    m.erase(dp->s);

    return 0;
}

我将我的类Data 实例存储在hash_map 中。我使用key 搜索特定数据成员,然后使用m.erase(dp-&gt;s) 删除该值。 m.erase(dp-&gt;s) 将删除dp 指向的对象。我可以在调用erase() 时使用dp-&gt;s,还是必须先复制然后erase()

std::string key_to_delete = dp->s;
m.erase(key_to_delete);

【问题讨论】:

    标签: c++ g++ hashmap


    【解决方案1】:

    查看implementation,似乎即使在删除节点(it 指向的对)之后,传递给erase 函数的键仍然被引用。如果dp 被删除,那么对dp-&gt;s 的引用将变得无效。然而hash_map 的实现仍在尝试取消引用它。失败。

    您需要传递一些保证在调用erase 时保持有效的内容。

    你可以

    m.erase(key);
    

    或者你可以使用find返回的迭代器来进行擦除:

    m.erase(it);
    

    【讨论】:

    • 谢谢!这是违反直觉的,但现在我在源代码中有证据。
    • 我不能直接使用keyit,因为实际代码有点复杂,而且从哈希映射中删除的地方,我无权访问@ 987654333@ 或 it 了。
    • 看来您必须复制一份(或后续问题!)
    猜你喜欢
    • 2012-06-23
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 2010-10-28
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    相关资源
    最近更新 更多