unordered_map 中的销毁顺序

Order of destruction in unordered_map

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

我的问题:

  1. 如果我 erase() 一个对象,它的析构函数试图在无序映射中寻找它自己,这是否有效?具体是先调用析构函数,还是先从unordered_map中移除对象,还是不保证?
  2. 如果 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} });
}