具有动态存储期限的Lambda [英] Lambda with dynamic storage duration

查看:77
本文介绍了具有动态存储期限的Lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据cppreference.com,仅在 直接初始化 。似乎没有一种方法可以直接通过 new 运算符直接使用lambda语法。

According to cppreference.com, C++11 lambda literal syntax is only legal to use in direct initialization. There doesn't seem to be a way to use the lambda syntax directly with the new operator.

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

I need to store a lambda function in the heap so that I can call it at some later point from a different thread. It's easy enough to make a copy of the lambda, but is there a simple way to allocate the lambda directly in the heap (dynamic storage duration) without first allocating it on the stack (automatic storage duration) and making a copy?

这是一个简单的示例:

#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;
}

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

The above program makes 2 copies of o (one in the capture, and another when the lambda is copied into the heap). Ideally, there would only be one copy or move, which would happen when the heap-allocated lambda captures a copy of o.

推荐答案

在C ++ 11中,lambda表达式始终会 生成某种形式的自动对象,无论是堆栈变量还是未命名的临时对象。

In C++11, a lambda expression will always result in some form of automatic object, whether a stack variable or an unnamed temporary. There's nothing you can do to change that.

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

In C++17, guaranteed elision gives us the ability to do this:

new auto(<lambda>)

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

This uses the memory allocated by new to store the result of that expression. There would be no temporary lambda object created here, nor would any copy/move constructor for the lambda be invoked. And most importantly, the language would not require that the lambda type have copy/move constructors that could be invoked.

需要确保可以省略以确保这一点。如果没有这种保证,那么您将依靠编译器对其进行优化。标准的允许这样的案例可以删除副本。是的,任何值得使用的编译器都可能会淘汰此类副本。

You need guaranteed elision to ensure this however. Without that guarantee, then you're banking on the compiler to optimize it. The standard permits such cases to elide the copy. And yes, any compiler worth using probably would elide such copies.

有了保证的省略率,您可以捕获固定类型,并且仍然可以工作而无需复制任何内容。在C ++ 17之前的版本中,即使取消了对lambda的调用,您的lambda仍需要具有复制或移动构造函数。

With guaranteed elision, you could capture immobile types and this would still work without copying anything. Pre-C++17, your lambda would still need to have a copy or move constructor, even though the call to it is elided.

这篇关于具有动态存储期限的Lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆