STL图:访问违规读取位置

STL map: Access violatoin reading location

这是我的代码:

class Base
{
public:
    virtual void show() const = 0;
};

class Child : public Base
{
private:
    static const int i = 1;
public:
    virtual void show() const
    {
        cout << i;
    }
};

map<int, const Base &> myMap{
    { 0, Child() },
    { 1, Child() },
};

Base & b = Child();

int main()
{
    b.show();

    myMap.at(0).show(); // This provokes the error

    system("pause>NUL");
    return 0;
}

如您所见,我正在尝试使用 global(或 static)数据,它将调用一些 virtual 函数。当我测试 Base & b = Child();main: b.show(); 时,一切顺利。

但是,如果我像上面那样使用 map,我会得到一个错误:

0xC0000005: Access violatoin reading location 0x00000000.

我尝试调试这段代码,我发现当它到达时 myMap.at(0).show();,我得到了这个:

好像虚函数的table是Unable to read...

然后我尝试使用指针:
map<int, Base *>{0, new Child()}.
这行得通。

看来这个错误是临时引用的。

但我不知道为什么 b 有效。 b也是临时参考。
在我看来,这个map包含了很多b.
为什么 b 有效而 map 无效?

您有一张参考临时文件的地图。我很惊讶甚至编译

map<int, Base &> myMap{
    { 0, Child() },
    { 1, Child() },
};

删除引用并切换到 unique_ptr

std::map<int, std::unique_ptr<Base>> myMap;

您可以在此地图中插入元素 using this method. This will prevent object slicing

你在这里再次做同样的事情

Base & b = Child();

You cannot hold non-const references to temporary objects

MSVC 确实允许影响对引用的临时引用,这意味着 Base & b = Child(); 被接受并正确处理,即使它是 不是 标准 C++ 并且被其他人拒绝编译器(并且可能会被更高版本的 MSVC 拒绝)

但即使是 MSVC 也不接受引用的 stl 容器。

因此您应该使用 map<int, Base>(无引用,存储对象的副本)或 map<int, Base *>(存储指向对象的指针)。在后一种情况下,you 必须明确处理对象的销毁。您还可以使用智能指针unique_ptrshared_ptr让stl关心自动销毁。