unordered_map 中的销毁顺序
Order of destruction in unordered_map
我有 unordered_map 个对象。每个对象在其析构函数中浏览无序映射以查找其他对象,然后调整这些其他对象。如果其他对象是僵尸对象,这将失败,但如果其他对象完全从 unordered_map 中删除,则没有问题。
我的问题:
- 如果我 erase() 一个对象,它的析构函数试图在无序映射中寻找它自己,这是否有效?具体是先调用析构函数,还是先从unordered_map中移除对象,还是不保证?
- 如果 unordered_map 被销毁,这是否有效?具体来说,unordered_map 是否会在调用每个单独的析构函数时处于有效状态?
The lifetime of an object of type T ends when [...] if T is a class type with a non-trivial destructor (12.4), the destructor call starts [...]
[§ 3.8/1 N4431]
然后,再往下
The properties ascribed to objects throughout this International Standard apply for a given object only during its lifetime
[§ 3.8/3 N4431]
最后
[...] after the lifetime of an object has ended [...] any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. [...] The program has undefined behavior if [...] the pointer is used to access a non-static data member or call a non-static member function of the object [...]
[§ 3.8/5 N4431]
因此,由于您必须对地图有某种引用(例如指针或实际引用,我在这里也将其算作指针),并且其生命周期已结束,因此访问成员函数(例如获取迭代器)将——据我阅读标准的这一部分——导致未定义的行为。
我也在查看标准中关于无序容器和一般容器的部分,但找不到上述异常或有关销毁期间状态的任何线索。
所以:不要这样做。既没有无序容器,也没有任何其他对象。
顺便说一句:当您对之后将被破坏的对象进行调整时,什么样的调整才有意义?
我想我找到了一个不错的解决方案。您可以将一个 unordered_map 封装在一个 class 中,并使用它的析构函数来引发一个标志,并在散列 table 中为 typaram 的对象的析构函数中将其检测为边缘情况。像这样:
template<typename K, typename V>
struct hash_table
{
unordered_map<K, V> map;
bool is_being_deleted = false;
~hash_table()
{
is_being_deleted = true;
}
};
struct PageRefrence
{
string str;
int page;
hash_table<string, PageRefrence>& refTable;
~PageRefrence()
{
if (refTable.is_being_deleted == true) // When the map is in the procces of deletion
return;
else
{ // Normal case
auto x = refTable.map.find(str);
cout << (*x).second.page;
}
}
};
int main()
{
hash_table<string, PageRefrence> refTable;
refTable.map.insert({ "HELP",{"HELP",42,refTable} });
}
我有 unordered_map 个对象。每个对象在其析构函数中浏览无序映射以查找其他对象,然后调整这些其他对象。如果其他对象是僵尸对象,这将失败,但如果其他对象完全从 unordered_map 中删除,则没有问题。
我的问题:
- 如果我 erase() 一个对象,它的析构函数试图在无序映射中寻找它自己,这是否有效?具体是先调用析构函数,还是先从unordered_map中移除对象,还是不保证?
- 如果 unordered_map 被销毁,这是否有效?具体来说,unordered_map 是否会在调用每个单独的析构函数时处于有效状态?
The lifetime of an object of type T ends when [...] if T is a class type with a non-trivial destructor (12.4), the destructor call starts [...]
[§ 3.8/1 N4431]
然后,再往下
The properties ascribed to objects throughout this International Standard apply for a given object only during its lifetime
[§ 3.8/3 N4431]
最后
[...] after the lifetime of an object has ended [...] any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. [...] The program has undefined behavior if [...] the pointer is used to access a non-static data member or call a non-static member function of the object [...]
[§ 3.8/5 N4431]
因此,由于您必须对地图有某种引用(例如指针或实际引用,我在这里也将其算作指针),并且其生命周期已结束,因此访问成员函数(例如获取迭代器)将——据我阅读标准的这一部分——导致未定义的行为。
我也在查看标准中关于无序容器和一般容器的部分,但找不到上述异常或有关销毁期间状态的任何线索。
所以:不要这样做。既没有无序容器,也没有任何其他对象。
顺便说一句:当您对之后将被破坏的对象进行调整时,什么样的调整才有意义?
我想我找到了一个不错的解决方案。您可以将一个 unordered_map 封装在一个 class 中,并使用它的析构函数来引发一个标志,并在散列 table 中为 typaram 的对象的析构函数中将其检测为边缘情况。像这样:
template<typename K, typename V>
struct hash_table
{
unordered_map<K, V> map;
bool is_being_deleted = false;
~hash_table()
{
is_being_deleted = true;
}
};
struct PageRefrence
{
string str;
int page;
hash_table<string, PageRefrence>& refTable;
~PageRefrence()
{
if (refTable.is_being_deleted == true) // When the map is in the procces of deletion
return;
else
{ // Normal case
auto x = refTable.map.find(str);
cout << (*x).second.page;
}
}
};
int main()
{
hash_table<string, PageRefrence> refTable;
refTable.map.insert({ "HELP",{"HELP",42,refTable} });
}