C ++ 11. Capturing a Lambdas item variable, "this" is a pointer in an STL list

I have a simple event system with a simple button. This system is driven by a list of std :: function with assigned lambdas inside.

Here is the complete class of buttons:

class Button {

private:

    Square square;
    Text label;
    bool hovered = false;
    std::function <void ()> on_mouse_enter;
    std::function <void ()> on_mouse_leave;

public:

    Button (const Square& SQUARE, const Text& LABEL):
        square {SQUARE},
        label {LABEL}
    {
        on_mouse_enter = [this] () {
            square.set_color(1, 1, 1);
        };

        on_mouse_leave = [this] () {
            square.set_color(0, 0, 0);
        };
    }

    std::function <void (const Render&)> get_rendering() {
        return [this] (const Render& RENDER) {
            RENDER.draw(square);
            RENDER.draw(label);
        };
    }

    std::function <void (const Point&)> get_updating() {
        return [this] (const Point& CURSOR) {
            if (not hovered) {
                if (is_including(square, CURSOR)) {
                   hovered = true;
                   if (on_mouse_enter)
                       on_mouse_enter();
                }
            } else
                if (not is_including(square, CURSOR)) {
                   hovered = false;
                   if (on_mouse_leave)
                       on_mouse_leave();
                }
        };
    }

};

      

And I add a button like this to the event manager, for example:

Button button {/*SOME_PARAMS_HERE*/};

mngr.push_to_render(button.get_render());
mngr.push_to_updater(button.get_updater());

      

It works fine, no problem, on_mouse_enter and on_mouse_leave work as intended.

But if I do something with the wrapper of the STL container like:

std::list <Button> sb;

sb.emplace_back(Button {/*SOME_PARAMS_HERE*/});

mngr.push_to_render(sb.back().get_render());
mngr.push_to_updater(sb.back().get_updater());

      

The whole thing is falling apart. on_mouse_enter and on_mouse_leave don't work like that.

When outputting debug messages I can see that the square accessed in this case in on_mouse_enter and on_mouse_leave are not the squares they should be, I can see that this is not what it should be.

What is wrong with such seizures and how can it be solved?

+3


source to share


1 answer


Don't write this

if you are going to copy. Regardless of what you grabbed, you are in charge of life time management.

Second, the pointer to the button passed to enter / leave makes a lot of sense.

std::function<void(Button*)> on_mouse_enter;
std::function<void(Button*)> on_mouse_leave;

      

Then we have:



    on_mouse_enter = [] (Button* but) {
        but->square.set_color(1, 1, 1);
    };

    on_mouse_leave = [] (Button* but) {
        but->square.set_color(0, 0, 0);
    };

      

and the copy constructor no longer leaves you pointers to another this

.

Finally, when you call on_mouse_enter

, go through this

.

+5


source







All Articles