C++ 如何减少Lambda扩展堆栈的使用

C++ 如何减少Lambda扩展堆栈的使用,c++,gcc,lambda,C++,Gcc,Lambda,我目前正在从事一个使用很多lambda函数的项目,我发现它们使用了很多堆栈,但我不明白为什么。我是一个相当新的C++,我更习惯于C.< 为了减少堆栈的使用并理解lambda是如何工作的,我编写了一些非常简单的代码来重现lambda的使用。我使用gcc和-Os选项编译以下代码 typedef struct structTest { uint32_t var1; uint32_t var2; } structTest; // Test 1 int main() { dost

我目前正在从事一个使用很多lambda函数的项目,我发现它们使用了很多堆栈,但我不明白为什么。我是一个相当新的C++,我更习惯于C.< 为了减少堆栈的使用并理解lambda是如何工作的,我编写了一些非常简单的代码来重现lambda的使用。我使用gcc和-Os选项编译以下代码

typedef struct structTest
{
    uint32_t var1;
    uint32_t var2;
} structTest;

// Test 1
int main()
{
    dostuff( [&]() -> structTest{ structTest $; $.var2 = 24; $.var1 = 48; return $; }() );
}

// Test 2
int main()
{
    dostuff( [&]() -> structTest{ structTest $; $.var2 = 24; $.var1 = 48; return $; }() );

    dostuff( [&]() -> structTest{ structTest $; $.var2 = 13; $.var1 = 42; return $; }() );
}
测试1使用了8个字节的堆栈,这是我没有预料到但可以理解的,但是测试2使用了16个字节的堆栈,我不明白为什么。我本以为会有8个字节,因为用于函数第一次调用的堆栈中的字节会被用于第二次调用

我猜这两个结构不会保留在堆栈上

利用臭氧对电堆进行分析,并在核子L476RG上运行。该项目是一个物联网项目,其中ROM和堆栈非常宝贵


有没有一种方法可以保持这种结构/lambda的使用,但减少堆栈的使用?

像这样的lambda的一个主要好处是,它们几乎可以简单地内联到周围的代码中。这就是为什么我们喜欢他们!没有新堆栈或跳转之类的开销

当然,内联使用了周围函数的堆栈来存储所有数据。这就是你观察到的

在任何其他“我不希望这是内联的”情况下,做任何你想做的事情。在这个特定的实例中,可能使用实际的函数而不是lambda,并在它们上添加一个“noinline”类型的属性(如何操作请参见工具链文档)

如果你想要一个为什么人们不经常使用C++来进行嵌入式编程的例子,这将是一个很好的例子。它是为更丰富的处理器设计的,在这些处理器中,我们通常并不关心是否会使用另外8个字节的堆栈—我们关心程序是否运行得很快,我们相信编译器会通过在有意义的地方进行内联来帮助我们做到这一点。您的环境和需求与社会契约不太匹配

肯定是返工或重载
dostuff
,所以您可以这样称呼它:

dostuff(48, 24);
…会更好吗

实施可以简单到:

__attribute__((noinline))
void doStuff(const uint32_t var1, const uint32_t var2)
{
   const structTest sT = {var1, var2};
   doStuff(sT);
}
在我看来,它的代码也少得多,而且更容易阅读


顺便说一句,虽然它在您的平台上工作,但我并不推荐使用
$
作为标识符。这是一个简单的问题,读者不太清楚。

你为什么不期待/理解这一点?我认为你需要解释你预期/期望的行为,以及为什么当前的行为对你来说是个问题。-此外,你是如何分析堆栈使用的?@康拉德鲁道夫:OP的期望听起来对我来说是合理的(不是C++ LAMBDAS的专家)。这是我们喜欢函子的原因之一,它们更容易内联。不幸的是,我不能给你一个如何重构代码的例子,因为在这个例子中根本不需要lambda。我使用Ozone来分析堆栈的使用情况,代码在NucleoL476RG上运行。我可以更新我的帖子,如果它不清楚,请做。无论如何,这在很大程度上取决于编译器/版本和优化设置。在带有
-O3
的g++9.1上,它不会占用任何堆栈空间(取决于
dostuff
的功能,否则会重用堆栈空间)。