首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >lambda捕获[&args.]之间的区别是什么?和[...args = std::forward<Args>(args)]

lambda捕获[&args.]之间的区别是什么?和[...args = std::forward<Args>(args)]
EN

Stack Overflow用户
提问于 2022-08-11 11:32:29
回答 1查看 157关注 0票数 7

我正在用实体组件系统编写一个简单的游戏。我的组件之一是NativeScriptComponent。它包含我的脚本的实例。我的想法是,我可以在任何时候创建我的NativeScriptComponent,然后对它进行Bind,实现Scriptable接口的任何类。之后,我的游戏的OnUpdate函数将自动实例化游戏中的所有脚本,并调用它们的OnUpdate函数。

我的脚本可以有自己的、不同的构造函数,所以在绑定脚本时,我需要将所有的参数转发给它们。

考虑以下代码:

代码语言:javascript
复制
#include <iostream>
#include <memory>
#include <functional>

using namespace std;

struct Scriptable
{
    virtual void OnUpdate() {};
};
struct MyScript : Scriptable 
{ 
    MyScript(int n) : value(n) {}
    void OnUpdate() override {cout << value;} 
    int value;
};

struct NativeScriptComponent
{
    unique_ptr<Scriptable> Instance;
    function<unique_ptr<Scriptable>()> Instantiate;

    template<typename T, typename ... Args>
    void Bind(Args&&... args)
    {
        // (A)
        Instantiate = [&args...]() { return make_unique<T>(forward<Args>(args)...);  };
        // (B) since C++20
        Instantiate = [...args = forward<Args>(args)]() { return make_unique<T>(args...);  };
    }
};

int main()
{
    NativeScriptComponent nsc;
    nsc.Bind<MyScript>(5);
    
    // [..] Later in my game's OnUpdate function:
    if (!nsc.Instance)
        nsc.Instance = nsc.Instantiate();
    nsc.Instance->OnUpdate(); // prints: 5

    return 0;
}

1)选项A和B的区别是什么?

代码语言:javascript
复制
Instantiate = [&args...]() { return make_unique<T>(forward<Args>(args)...);  };

vs

代码语言:javascript
复制
Instantiate = [...args = forward<Args>(args)]() { return make_unique<T>(args...);  };

  1. 为什么不能在选项B中使用forward<Args>(args) in make_unique

perfectly-forwarded?

  1. 既是A又是B
EN

回答 1

Stack Overflow用户

发布于 2022-08-11 11:59:12

A通过引用捕获参数,然后完美地转发到make_unique中。不幸的是,此时引用(可能)正在悬空,因此在您的示例中调用Instantiate具有未定义的行为。

B将参数完美地转发到闭包对象的数据成员中,然后将这些数据成员复制到make_unique中。如果不标记lambda mutable,就不能在此转发,因为lambda的主体是闭包对象的const成员函数。

A不能转发r值,对它们的引用就会悬空。B不能转发值,它可以复制。

如果您只想实例化一个Scriptable,那么可以将B中的lambda标记为mutable,然后移动到其中。如果要构造多个Scriptable,则必须进行一些复制。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73319953

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档