C ++ лямбда захватывает пустую строку

0

У меня есть класс сообщений с кнопками, которые выполняют заданную функцию при нажатии:

// cMessage.h
#include "cButton.h"

class cMessage{
    public:
        std::vector<cButton*> button;
        cMessage(const std::vector<std::function<void()> >& effect);
        ~cMessage();
        void alert();};

// cMessage.cpp
cMessage::cMessage(const std::vector<std::function<void()> >& effect){
    for(unsigned int i = 0; i < effect.size(); i++)
        button.push_back(new cButton(effect[i], this)); }

cMessage::~cMessage(){
    for(unsigned int i = 0; i < button.size(); i++)
        delete button[i];}

void cMessage::alert(){
    delete this;}

// cButton.h
class cMessage;

class cButton{
    private:
        cMessage* alert;
        const std::function<void()> effect;
    public:
        cButton(const std::function<void()>& effect, cMessage* alert);
        void onClick();}

// cButton.cpp
cButton::cButton(const std::function<void()>& effect, cMessage* alert): effect(effect), alert(alert){}

void cButton::onClick(){
    if(alert)  alert->alert();
    if(effect) effect();}

Проблема возникает, когда я передаю лямбда-функцию, потому что когда я позволяю этой лямбда-функции захватывать пару, состоящую из строки и unsigned int, строка пуста в момент выполнения функции. Однако unsigned int все равно 1.

// main.cpp
#include "cMessage.h"    

int main(){
    cMessage* message;
    {const pair<const string, const unsigned int> var("test", 1);
     std::function<void()> f = [var](){ std::cout << var.first << std::endl << var.second << std::endl; } };
     message = new cMessage( {f} );}
    message->button[0]->onClick();

    return 0;}

С некоторыми еще couts я обнаружил, что в конструкторе cButton строка по-прежнему "проверена". Что-то, что делает его еще более странным, заключается в том, что когда я напрямую конструирую кнопку, проблема не возникает.

Проблема решена. Это было вызвано неопределенным поведением, потому что функция лямбда вызывалась после того, как кнопка была удалена (кнопка совершила вызов своего сообщения непосредственно перед тем, чтобы ее удалить). Это также объясняет, почему прямое создание кнопки не создает проблем. Меня удивляет, что у меня еще не было никаких проблем. Спасибо за вашу помощь

  • 1
    Вы должны создать stackoverflow.com/help/mcve . Какой компилятор вы используете?
  • 0
    MinGW, и это на самом деле минимальный код, который выдает ошибку
Показать ещё 16 комментариев
Теги:
c++11
lambda

1 ответ

0
Лучший ответ

Я предлагаю переосмыслить

new cButton(this, effect[i]);

В противном случае передайте больше кода.

--- редактировать ---

Код, который вы вставили, дает правильный выход:

#include <iostream>
#include <vector>
#include <string>
#include <functional>
#include <utility>

class cButton{
    private:
        const std::function<void()> effect;
    public:
        cButton(const std::function<void()>& effect);
        void onClick();};

cButton::cButton(const std::function<void()>& effect): effect(effect){}


class cMessage{
    public:
        std::vector<cButton*> button;
        cMessage(const std::vector<std::function<void()> >& effect);};


cMessage::cMessage(const std::vector<std::function<void()> >& effect){
    for(unsigned int i = 0; i < effect.size(); i++)
        button.push_back(new cButton(effect[i])); }


void cButton::onClick(){
    if(effect) effect();
    }

int main(){
    cMessage* message{};
    {
        const std::pair<const std::string, const unsigned int> var("test", 1);
        std::function<void()> f = [var](){ std::cout << var.first << std::endl << var.second << std::endl; };
        message = new cMessage( {f} );
    } 
    message->button[0]->onClick();
}

Output:
test
1
  • 0
    Я нашел проблему, новый cButton (this, effect [i]); часть была существенной: с этим аргументом кнопка предупредила бы сообщение, когда оно было нажато. Сообщение затем удалило все кнопки и себя. Но после вызова этой функции оповещения кнопка все еще использовала некоторые из своих функций-членов, что привело к неопределенному поведению.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню