gpt4 book ai didi

c++ - 具有动态存储持续时间的 Lambda

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:55:32 25 4
gpt4 key购买 nike

根据 cppreference.com,C++11 lambda 文字语法仅在 中使用合法 direct initialization 。似乎没有办法直接通过 new 运算符使用 lambda 语法。

我需要在堆中存储一个 lambda 函数,以便稍后可以从不同的线程调用它。制作 lambda 的拷贝很容易,但是有没有一种简单的方法可以直接在堆中分配 lambda(动态存储持续时间),而无需先在堆栈上分配它(自动存储持续时间)并制作拷贝?

这是一个简单的例子:

#include <cstdio>
#include <cassert>

struct MyObj {
int value;
int copies;
int moves;

MyObj(int v): value(v), copies(0), moves(0) {
printf("Created object with value %d.\n", value);
}

MyObj(const MyObj &other): value(other.value),
copies(other.copies+1), moves(other.moves) { }

MyObj(const MyObj &&other): value(other.value),
copies(other.copies), moves(other.moves+1) { }
};

int main (int argc, char **argv) {
MyObj o { 5 };
// Create lambda on stack (automatic storage duration)
auto f = [o] {
printf("Object value is %d\n", o.value);
printf("%d copies, %d moves...\n", o.copies, o.moves);
};
// Copy lambda to heap (dynamic storage duration)
decltype(f) *g = new decltype(f)(f);
// Call the copy
(*g)();
return 0;
}

上面的程序制作了 2 个 o 拷贝(一个在捕获中,另一个在 lambda 被复制到堆中时)。理想情况下,只有一个拷贝或移动,这将在堆分配的 lambda 捕获 o 的拷贝时发生。

最佳答案

在 C++11 中,lambda 表达式总是会产生某种形式的自动对象,无论是堆栈变量还是未命名的临时对象。您无能为力。

在 C++17 中,保证省略使我们能够做到这一点:

new auto(<lambda>)

这使用 new 分配的内存来存储该表达式的结果。这里不会创建临时 lambda 对象,也不会调用 lambda 的任何复制/移动构造函数。最重要的是,该语言不需要 lambda 类型可以调用的复制/移动构造函数。

不过,您需要保证省略以确保这一点。如果没有这种保证,那么您将依赖编译器对其进行优化。标准允许这种情况下省略拷贝。是的,任何值得使用的编译器都可能会删除此类拷贝。

通过有保证的省略,您可以捕获固定类型,并且这仍然可以在不复制任何内容的情况下工作。在 C++17 之前,您的 lambda 仍然需要一个复制或移动构造函数,即使对它的调用被省略。

关于c++ - 具有动态存储持续时间的 Lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37924996/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com