为什么我不能从析构函数调用c++中的集合擦除?

jjhzyzn0  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(114)

我在学习C入门书第13.4章时遇到了一个问题,我在C中定义了两个class类型,其中一个类包含一个set变量,它将pointers存储到另一个类类型中,现在,我为类类型record定义了一个destructor,当该类类型record的元素被析构时,destructor会删除类的file集合中存储的地址,但是我运行这个程序的时候,系统崩溃了,我只想知道发生了什么,非常感谢。
实际上,这是C++初级读本13.4中的一个已知问题。我编写了一个类似但更简单的代码来重现相同的错误,代码如下:

#include <iostream>
#include <memory>
#include <set>
class file;
class record {
public:
    ~record() {
        deletefun();
    }
    
    int x;
    std::set<file*> file_log;
    void deletefun();
};
class file {
public:
    std::set<record*> ptr_to_record;
    void remove(record* e) 
    { 
        std::cout << e->x << std::endl;
        ptr_to_record.erase(e); 
    }
};
void record::deletefun() {
    for (auto i : file_log) 
        i->remove(this);
}
int main() {
    record e1;
    e1.x = 10;
    file n1;
    e1.file_log.insert(&n1);
}

我尝试输出类变量“file”的大小,结果是1,这意味着集合中存储了地址,但是我根本无法访问集合,甚至连开始元素都无法访问。
我的操作系统是Windows,我在Visual Studio 2022中编译了这段代码。

pengsaosao

pengsaosao1#

e1n1之前创建。
因此,e1n1之后被销毁。
因此,当您到达e1的销毁时,n1已经被销毁,并且i->remove(this);尝试访问被销毁的对象。
您需要确保所有file的寿命都比存储其地址的record长。

相关问题