根据cppreference.com,C++ 11 lambda文字语法仅适用于直接初始化.似乎没有办法直接在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;
}
Run Code Online (Sandbox Code Playgroud)
上面的程序制作了2个副本o(一个在捕获中,另一个在将lambda复制到堆中时).理想情况下,只有一个副本或移动,这将在堆分配的lambda捕获副本时发生o.
Nic*_*las 10
在C++ 11中,lambda表达式总是会产生某种形式的自动对象,无论是堆栈变量还是未命名的临时对象.你无能为力改变这一点.
在C++ 17中,保证的elision使我们能够做到这一点:
new auto(<lambda>)
Run Code Online (Sandbox Code Playgroud)
这使用分配的内存new来存储该表达式的结果.这里不会创建临时的lambda对象,也不会调用lambda的任何复制/移动构造函数.最重要的是,该语言不要求lambda类型具有可以调用的复制/移动构造函数.
但是,您需要保证省略以确保这一点.如果没有这种保证,那么您将依赖编译器来优化它.该标准允许此类案件免于复制.是的,任何值得使用的编译器都可能会忽略这些副本.
有了保证的elision,你可以捕获不动的类型,这仍然可以工作而无需复制任何东西.在前C++ 17中,你的lambda仍然需要有一个复制或移动构造函数,即使它的调用被省略了.
该auto关键字是合法的new表达式,它允许你这样做:
// Create lambda directly in heap (dynamic storage duration)
auto g = new auto([o] {
printf("Object value is %d\n", o.value);
printf("%d copies, %d moves...\n", o.copies, o.moves);
});
Run Code Online (Sandbox Code Playgroud)
这是整个(更新的)示例:
#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 directly in heap (dynamic storage duration)
auto g = new auto([o] {
printf("Object value is %d\n", o.value);
printf("%d copies, %d moves...\n", o.copies, o.moves);
});
// Call heap lambda
(*g)();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
以上只需要一个副本o- 至少在我的平台上(Apple LLVM版本7.0.0(clang-700.1.76)).
| 归档时间: |
|
| 查看次数: |
611 次 |
| 最近记录: |