这是我的代码:
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();
时,我得到了这个:
似乎虚函数表是Unable to read
...
然后我尝试使用指针:
map<int, Base *>
和{0, new Child()}
。
这很有效。
所以看来这个错误来自临时参考。
但我不知道为什么b
有效。 b
也是临时参考
在我看来,这个map
包含许多b
为什么b
有效,而map
无效?
答案 0 :(得分:6)
你有一个临时参考地图。我甚至惊讶于编译
map<int, Base &> myMap{
{ 0, Child() },
{ 1, Child() },
};
删除参考并切换到unique_ptr
std::map<int, std::unique_ptr<Base>> myMap;
您可以在此地图using this method中插入元素。这会阻止object slicing。
你在这里再做同样的事情
Base & b = Child();
答案 1 :(得分:0)
MSVC允许影响临时参考,这意味着Base & b = Child();
被接受并正确处理,即使它不标准C ++并被其他编译器拒绝(并且可能是被更高版本的MSVC拒绝
但即使是MSVC也不接受stl容器的引用。
因此,您应该使用map<int, Base>
(无参考,存储对象的副本)或map<int, Base *>
(存储指向对象的指针)。在后一种情况下,你必须明确地处理对象的破坏。您还可以使用智能指针,unique_ptr
或shared_ptr
让stl关注自动销毁。