4

Here is my code:

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;
}

As you see, I'm trying to use a global(or static) data, which will call some virtual functions. When I test Base & b = Child(); and in main: b.show();, everything goes well.

But, if I use map like above, I will get an error:

0xC0000005: Access violatoin reading location 0x00000000.

I've tried to debug this code and I found that when it arrived myMap.at(0).show();, I got this:
enter image description here

It seems that the table of virtual functions is Unable to read...

Then I tried to use the pointer:
map<int, Base *> and {0, new Child()}.
This works.

So it seems that this error comes from temporary reference.

But I don't know why b works. b is a temporary reference too.
In my opinion, this map contains many b.
Why does b works whereas map doesn't work?

Yves
  • 11,597
  • 17
  • 83
  • 180

2 Answers2

7

You have a map of references to temporaries. I'm surprised that even compiled

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

Drop the reference and switch to unique_ptr

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

You can insert elements into this map using this method. This will prevent object slicing.

You do the same thing again here

Base & b = Child();

You cannot hold non-const references to temporary objects

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • 1
    thx. This can compile because I am using the stupid microsoft visual studio. – Yves Jul 30 '15 at 12:14
  • Now I try like this: `map myMap`. But still, I got the same error. – Yves Jul 30 '15 at 12:18
  • `unique_ptr` is the smart pointer. Are you sure that this can solve the error? Seriously for now I even don't know why I get this error ----- I don't think it's because I didn't use `unique_ptr`. – Yves Jul 30 '15 at 12:23
  • Which version of Visual Studio are you using? It should be there in at least 2010. – Paani Jul 30 '15 at 12:24
  • Did you `#include `? – Cory Kramer Jul 30 '15 at 12:25
  • @Tomas "You do the same thing again here Base & b = Child();" – SChepurin Jul 30 '15 at 12:32
  • It seems that you are talking about reference and smart pointer... I tried like this too: `map`, but I still got the same error. I don't know why. – Yves Jul 30 '15 at 12:33
  • @SChepurin thanks guys. About what you are talking about, I totally understand now. But it's not about my problem... I've tried `map` but I still got the same error. – Yves Jul 30 '15 at 12:36
  • OK, now I know. `map` cant take any temporary value. This is why you tell me to use pointer. thx. – Yves Jul 31 '15 at 07:46
0

MSVC does allow to affect a temporary to a reference, meaning that Base & b = Child(); is accepted and correctly processed, even it is not standard C++ and is rejected by other compilers (and could be rejected by a later version of MSVC)

But even MSVC does not accept stl containers of references.

So you should either use a map<int, Base> (no ref, store a copy of the object), or a map<int, Base *> (stores a pointer to the object). In the latter case, you must deal explicitely with the destruction of the object. You can also use smart pointers, unique_ptr or shared_ptr to let the stl cares for automatic destruction.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252