【问题标题】:C++ Lambda captures empty stringC++ Lambda 捕获空字符串
【发布时间】:2014-11-14 15:01:54
【问题描述】:

我有一个带有按钮的消息框类,这些按钮在被点击时执行给定的功能:

// 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();}

当我传递一个 lambda 函数时会出现问题,因为当我让该 lambda 函数捕获由一个字符串和一个无符号 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 的构造函数中,字符串仍然是“test”。 更奇怪的是,当我直接构造一个按钮时,并没有出现问题。

问题已解决 它是由未定义的行为引起的,因为在删除按钮之后调用了 lambda 函数(按钮在此之前调用了它的消息,导致它被删除)。这也解释了为什么直接创建按钮不会产生问题。令我惊讶的是,我还没有任何其他问题。感谢您的所有帮助

【问题讨论】:

  • 您应该创建stackoverflow.com/help/mcve。你用什么编译器?
  • MinGW,这实际上是产生错误的最小代码
  • effect的类型是什么?
  • 应该是最少的完整代码
  • @RTCgee MCVE 的目标是让我从字面上将您的代码复制到我的窗口中并编译/运行它,看看我是否可以“验证”您的问题。

标签: c++ c++11 lambda


【解决方案1】:

我建议重新考虑

new cButton(this, effect[i]);

否则共享更多代码。

--- 编辑---

你粘贴的代码appears to produce the right output

#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

【讨论】:

  • 我找到了问题,新的cButton(this, effect[i]);部分是必不可少的:使用此参数,按钮将在按下时提醒消息。然后该消息删除了所有按钮及其本身。但是在调用了这个警报函数之后,按钮仍然使用了它的一些成员函数,导致了未定义的行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
相关资源
最近更新 更多