c++ - 在没有 std::function 的情况下将 lambdas/函数存储在 std::vector 中

标签 c++ vector lambda

请记住,我正在努力使代码尽可能快,因此包含分配或其他慢速代码的建议并不是真正的选择。

我有一个正在构建的游戏的渲染系统,我试图将所有渲染过程存储在一个函数 vector 中,例如:

if(Monster.IsAlive)
{
    PushRender([...](){ // "..." means some stuff that I need to capture
        // Rendering the monster here...
    });
}

在每个循环结束时,我遍历我存储的所有渲染并渲染它们,之后我清除数组。

我希望能够拥有一个包含多个不同函数的 vector ,并且能够访问本地变量或复制到函数中的变量(例如,lambda 捕获允许我将变量发送到函数而不更改函数的签名函数)或能够存储成员函数,这样我就可以访问对象的属性。

现在,我尝试了几种方法来使这个系统正常工作:

  • 我试图将所有内容存储在 std::vector<std::function<void()>> 中:

    问题:std::function似乎在循环的每次迭代中分配和释放内存,这对我来说真的很关键,所以std::function除非我能找到在不影响性能的情况下使用它的原因,否则这不是一个选项。

  • 尝试使用 std::vector<void(*Render)()> :

    问题:我不能将 lambda 与此选项一起使用,我也不能将成员函数与它们一起使用(至少我不能)。所以只有非成员的功能对我来说是个问题。

我想从系统得到的东西:

  • 要快,尽可能快。
  • 无需使用模板即可运行多个不同的函数(我想要一个包含所有函数的 std::vector)

有人知道如何实现这样的系统吗?

如果我的解释不够好,这里有一个例子:

using Func = ...; // std::function<void()> for example

std::vector<Func> Functions;

while(Running)
{
    // clear all the rendering
    Functions.clear();

    if(Monster.IsAlive)
    {
        // 1. 
        Functions.push_back(Monster.Render); // Monster.Render = Function
        // Or 2.
        Functions.push_back(RenderMonster); // RenderMonster = Function
        // Or 3.
        Functions.push_back([] () {
            RenderImage(MonsterImage, X, Y);
            //....
        }); 
    }

    //... More code here

    // Render everything that is saved so far 
    for(Func func : Functions)
    {
        func();
    }
}

最佳答案

so suggestions that contain allocations or other slow code is not really an option.

这显示了一种误解。分配不一定慢。避免堆分配的代码并不总是很快。您可以提供自己的 allocators (大多数标准 containers 有一个可选的分配器模板参数,例如 std::vector 的第二个模板参数)如果你相信你可以做得更快。

但是,您可以存储指向 lambda 的智能指针,也许使用 std::unique_ptr<std::function<void(void)>>

您确实需要管理这些 lambda 的生命周期。

Problem: std::function seem to allocate and deallocate memory every iteration of the loop, which is really critical to me,

你真的确定吗? 您真的进行了基准测试吗?在许多情况下,它对您来说已经足够快了(性能问题可能出在其他地方)。

我认为对于游戏渲染而言,瓶颈不会出现在您今天认为的位置。 您需要profile 你的整个游戏。当然,出于基准测试目的,您需要启用 compiler optimizations .另见 this (并点击那里的链接)。

典型的堆分配(使用 ::operator newmalloc ....)通常需要不到一微秒(但有时更多)。在大多数情况下(但不是全部),这不是性能问题。

(I want a single std::vector that contain all the functions)

这很容易。做一个tagged union类型,也许使用 std::variant , 然后有一个 std::vector这种类型的。或者,如果您有一个指针 vector ,创建一个公共(public)父类(super class)(带有一些虚函数)并有一个指向该类的指针 vector 。

关于c++ - 在没有 std::function 的情况下将 lambdas/函数存储在 std::vector 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48064433/

相关文章:

c++ - 避免为自定义类使用初始化列表

c++ - g++ 中奇怪的 C++ 构造函数/复制构造函数问题

c++ - 在 C++ 中返回 vector 标准

c++ - ADL 是否与命名的 lambda 一起使用?

c++ - 使用现代 OpenGL 渲染纹理

c++ - 将指向结构体数组的指针传递给函数的区别

javascript - 在javascript中旋转向量

C++: vector 到字符串流

Java 泛型和流

java - 如何使用 Java 8 Lambdas 执行以下操作