考虑以下程序,这是一个试图用一些遗留代码重现问题的最小示例:
#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->s)
删除该值。 m.erase(dp->s)
将删除dp
指向的对象。我是否可以在调用 erase()
时使用 dp->s
,或者我必须先复制一份然后再 erase()
:
std::string key_to_delete = dp->s;
m.erase(key_to_delete);
最佳答案
查看 implementation ,似乎即使在节点(it
指向的对)被删除后,传递给 erase
函数的键仍然被引用。如果 dp
被删除,那么对 dp->s
的引用将变得无效。然而 hash_map
的实现仍在尝试取消引用它。失败。
您需要传递一些保证对 erase
的调用保持有效的内容。
你可以
m.erase(key);
或者您可以使用 find
返回的迭代器来执行删除:
m.erase(it);
关于c++ - gnu C++ hash_map : erasing a key: defined?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18711298/