unordered_map中的销毁顺序

Order of destruction in unordered_map

本文关键字:顺序 map unordered      更新时间:2023-10-16

我有一个对象的unordered_map。每个对象在其析构函数中浏览无序映射以查找其他对象,然后调整这些其他对象。如果其他对象是僵尸对象,这将失败,但如果其他对象完全从unordered_map中删除,则没有问题。

我的问题:

  1. 如果我擦除()一个对象,它的析构函数试图在无序映射中寻找自己,这个工作吗?具体来说,是先调用析构函数,还是先从unordered_map中删除对象,还是没有保证?
  2. 如果unordered_map被销毁,这个工作吗?具体来说,当每个单独的析构函数被调用时,unordered_map是否处于有效状态?

类型T的对象的生命周期在[…]如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用开始[…]

[§3.8/1 N4431]

再往下

本国际标准中赋予对象的属性仅在给定对象的生命周期内适用

[§3.8/3 N4431]

最后

[…在对象的生命周期结束后[…]任何指向对象所在的存储位置的指针都可以被使用,但使用方式有限。[…程序有未定义的行为,如果…指针用于访问非静态数据成员或调用对象的非静态成员函数[…]

[§3.8/5 N4431]

所以,既然你必须有某种类型的引用(例如指针,或者一个真正的引用,我在这里也算作指针)到map,并且它的生命周期已经结束,访问成员函数(例如获取迭代器)将——就我读到这部分标准而言——导致未定义行为。

我也看了标准中关于无序容器和一般容器的部分,没有找到上述的例外或任何关于销毁期间状态的线索。

So:不要这样做。不能使用无序容器,也不能使用任何其他对象。


BTW:什么类型的调整是有意义的,当你做的对象将被销毁之后的时刻?

我想我找到了一个不错的解决方案。您可以在类中封装一个unordered_map,并使用它的析构函数引发一个标志,并在哈希表中为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} });
}