【问题标题】:Passing lambda to an object and modify that object from inside the lambda将 lambda 传递给一个对象并从 lambda 内部修改该对象
【发布时间】:2023-03-06 20:07:01
【问题描述】:

我的代码如下所示:

struct LambdaContainer{ 
    std::function<void(void)> f;
    float x = 10;
}

struct MyClass{
    LambdaContainer c;

}
void someFunction(){
    MyClass ins;
    LambdaContainer cont;
    cont.f = [&cont](){
        // I want to modify 'x' of LambdaContainer that is inside MyClass

        cont.x = 10; // won't work because cont will be copy constructed
                     // and this cont might not exist anymore
    };
    ins.c = cont;
    aVectorSomewhere.push_back(ins);
}

有什么方法可以捕获 LambdaContainer 的“cont”,以便它指的是从哪里调用 lambda? (顺便说一下,我没有使用指针)

感谢您提供这么好的答案 :) 我想我现在可以让它工作了

【问题讨论】:

  • 好像是XY problem实际问题是什么?一旦你陈述了实际问题,你可能会有一个简单的解决方案。
  • 我正在制作一个游戏,其中每个敌人都有独特的路线。我不想为我拥有的每个对象子类化我的敌人脚本,所以我试图让它发挥作用,并在我的初始化代码中对路由进行编码。所以我打算做的是传递一堆 lambda。

标签: c++ c++11 lambda capture


【解决方案1】:

不捕获cont,而是将其传递给存储的lambda:

class LambdaContainer
{ 
private:
    std::function<void(LambdaContainer&)> f;

public:
    float x = 10;

    void call_f()
    {
        f(*this);
    }
};

void someFunction()
{
    MyClass ins;
    LambdaContainer cont;
    cont.f = [](LambdaContainer& self)
    {    
        self.x = 10;
    };

    ins.c = cont;
    aVectorSomewhere.push_back(ins);
}

当您想要调用 lambda 时,只需从现有实例执行 LambdaContainer::call_f 或添加一种从 MyClass 调用 call_f 的方法,具体取决于您的设计。

【讨论】:

    【解决方案2】:

    只要不要不必要地复制或分配东西,就可以了(更不用说效率更高了):

    struct LambdaContainer { 
        std::function<void(void)> f;
        float x = 10;
    };   
    struct MyClass {
        LambdaContainer c;
        MyClass(const MyClass&) = delete; // noncopyable
        MyClass& operator=(const MyClass&) = delete;
    };
    void someFunction(){
        MyClass ins;
        ins.c.f = [&ins](){
            ins.c.x = 10;
        };
        aVectorSomewhere.emplace_back(std::move(ins));
    }
    

    【讨论】:

      【解决方案3】:

      ins 更改为动态分配并将MyClass* 指针存储在您的向量中(使用std::unique_ptr)。这样,lambda 捕获的地址在对象的生命周期内不会改变,因为不涉及复制。

      struct LambdaContainer {
          std::function<void(void)> f;
          float x = 10;
      };
      
      struct MyClass {
          LambdaContainer c;
      };
      
      std::vector<std::unique_ptr<MyClass>> aVectorSomewhere;
      
      void someFunction() {
          std::unique_ptr<MyClass> ins(new MyClass);
          LambdaContainer &cont = ins->c;
          cont.f = [cont]() {
              cont.x = 10;
          };
          aVectorSomewhere.push_back(std::move(ins));
      }
      

      然后,稍后调用 lambda:

      aVectorSomewhere[index]->c.f();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-21
        • 1970-01-01
        • 1970-01-01
        • 2015-09-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多