簡體   English   中英

在沒有std :: function的std :: vector中存儲lambdas / functions

[英]Store lambdas/functions in std::vector without std::function

切記,我正在嘗試使代碼盡可能快,因此包含分配或其他慢速代碼的建議實際上不是一種選擇。

我有一個正在構建的游戲的渲染系統,並且試圖將所有渲染過程存儲在功能向量中,例如:

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

在每個循環的末尾,我都要檢查存儲的所有渲染,然后渲染它們,然后清除數組。

我希望有一個包含多個不同函數的向量,並能夠訪問局部變量或復制到函數中的變量(例如,lambda capture讓我在不更改函數簽名的情況下將變量發送給函數)或能夠存儲成員函數,以便我可以訪問對象的屬性。

現在,我嘗試了幾種方法來使該系統正常工作:

  • 我試圖將所有內容存儲在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();
    }
}

因此,包含分配或其他慢代碼的建議實際上不是一個選擇。

這顯示了一個誤解。 分配不一定很慢。 避免堆分配的代碼並不總是很快。 如果您認為可以做得更快,則可以提供自己的分配器 (大多數標准容器都有一個可選的分配器模板參數,例如std::vector的第二個模板參數)。

但是,您可以使用std::unique_ptr<std::function<void(void)>>存儲指向lambda的智能指針。

您確實需要管理這些Lambda的生存期。

問題: std::function似乎在循環的每次迭代中都分配和釋放內存,這對我來說真的很關鍵,

你真的確定嗎? 你真的基准了嗎? 在許多情況下,它對您來說足夠快(並且性能問題可能在其他地方)。

我認為對於游戲渲染而言,瓶頸不會像今天那樣。 您需要配置整個游戲。 當然,出於基准測試目的,您需要啟用編譯器優化 另請參見 (並按照鏈接那里)。

典型的堆分配(使用::operator newmalloc ....)通常花費不到一微秒的時間(但有時要多得多)。 在大多數情況下(但不是全部),這不是性能問題。

(我想要一個包含所有功能的std :: vector)

這很容易。 使用std::variant一個標記的聯合類型,然后使用此類std::vector 或者,如果您有一個指針向量,則創建一個公共的超類(帶有一些虛函數)並具有一個指向該類的指針向量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM