我正在用实体组件系统编写一个简单的游戏。我的组件之一是NativeScriptComponent。它包含我的脚本的实例。我的想法是,我可以在任何时候创建我的NativeScriptComponent,然后对它进行Bind,实现Scriptable接口的任何类。之后,我的游戏的OnUpdate函数将自动实例化游戏中的所有脚本,并调用它们的OnUpdate函数。
我的脚本可以有自己的、不同的构造函数,所以在绑定脚本时,我需要将所有的参数转发给它们。
考虑以下代码:
#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的区别是什么?
Instantiate = [&args...]() { return make_unique<T>(forward<Args>(args)...); };vs
Instantiate = [...args = forward<Args>(args)]() { return make_unique<T>(args...); };forward<Args>(args) in make_unique?perfectly-forwarded?
发布于 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,则必须进行一些复制。
https://stackoverflow.com/questions/73319953
复制相似问题