简体   繁体   中英

Unexpected behavior of vectors when using references

I'm creating a game with SDL that usually use events and I've always encountered this weird behavior of vector, and I assume that it is due to the use of reference because I'm more likely to do a pass by reference.

game.cpp

Events e;
SDL_Event sdle;

// Loop until someone hits the main switch
while (SWITCH)
{
    // Poll events
    while (SDL_PollEvent(&sdle) != 0)
    {
        // Execute event callbacks
        e.exec_events(sdle); // DEBUG BREAKPOINT HERE
    }
}

events.h

struct Listener
{
    SDL_Rect* rect;

    std::function<void()> on_clicked;
    std::function<void()> on_mouse_over;
    std::function<void()> on_mouse_out;
};

Listener l;
SDL_Rect rect = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
l.rect = &rect;
l.on_mouse_over = []() {
    Game::showerrmsg("Hovered!", "Hovered!");
};
e.add_listener(&l);

events.cpp

std::vector<Listener*> listeners;

// I've passed the sdle here
void Events::exec_events(SDL_Event& e)
{
    analyze(e);
}

// from exec_events, sdle will be passed here
void Events::analyze(SDL_Event& e)
{
    // The problem starts here after hitting the above line
    switch (e.type)
    {
    case SDL_MOUSEMOTION:
        currentEvent = MOUSE_MOVE;
        break;
    case SDL_MOUSEBUTTONDOWN:
        currentEvent = MOUSE_CLICK;
        break;
    case SDL_MOUSEBUTTONUP:
        currentEvent = MOUSE_CLICKED;
        break;
    }

    // .......
}

DEBUG POINT:

Before hitting switch (e.type)

正常 After hitting switch (e.type)

意外

Looks like the objects were deallocated. I don't know what happened

I've tried allocating the listeners vector in the heap but still I got the same problem. Finally, I used pass by reference with pointers and it worked, it didn't mess up the vector. I can't explain this, and ended up asking myself, are pointers better than references (I know pointers are powerful), are references more dangerous than pointers?

A vector of references will not work. The contents of a vector should be assignable and references are not.

So your attempt at using pointers overcomes the problem but that's laden with problems as well. What would happen if the pointers are deallocated somewhere else? Consider using smart pointers

are references more dangerous than pointers?

update

Well raw pointers are dangerous. And that's why you should consider using Smart Pointers

But I wouldn't recommend allocating your vector on the heap. Is your app multithreaded? Would it be thread safe?

are references more dangerous than pointers?

No, in some over simplification these are the same where the pointers can be changed while the reference can't be changed.

There are some other differences as it is undefined behavior to use a nullptr for references.

It is also not specified how the reference needs to be represented. So this can't be used to be binary compatible.

In case a reference suffice, I don't see a reason to not use it.

I'd overcome the problem by replacing Listeners* with Listeners

typedef std::map<str, Listener> listeners_map;
listeners_map listeners;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM