假设复制变量具有所需的副作用。我想声明一个复制变量的lambda,但不会使用该变量。这样做的最低要求是什么?
Copiable copyable;
auto lambda1 = [=](){};
auto lambda2 = [copyable](){};
auto lambda3 = [=](){ copyable; }
auto lambda4 = [=](){ volatile copy = copyable; }
lambda1
使用隐式捕获,由于正文没有提到copyable
,我不相信它实际上会复制它。
lambda2
使用显式捕获,似乎根据this,它应该通过副本捕获。是否允许编译器删除副本?有关此问题的另一个讨论,请参见this。
lambda3
使用隐式捕获,但正文提到了copyable
。这是否构成copyable
的 odr-use ?
lambda4
使用隐式捕获并强制另一个volatile
副本。我确信这确实会有效,但它的副本数量超过了最低限度。
激励案例:我需要在完成任意数量的lambda调用后运行清理,可能在不同的线程中。我可以通过使用std::shared_ptr
和一个运行清理的自定义删除器来实现这一点,并以某种方式将其传递给每个lambda。然后,当所有共享ptrs超出范围时,清理将运行。
修改:lambda3
和lambda4
错过=
进行隐式捕获。
答案 0 :(得分:4)
执行此操作所需的最低要求是什么?
按值显式捕获,如lambda2
。
lambda1
使用隐式捕获,由于正文并未提及可复制,我不相信它实际上会复制它。
那是对的。变量只有在lambda中 odr-used 时才会被隐式捕获。
lambda2
使用显式捕获,似乎根据this,它应该通过副本捕获。
那是对的。无论是否使用,都将捕获任何明确捕获的变量。这是您希望确保捕获对象的目的。
编译器是否允许删除副本?有关此问题的另一个讨论,请参见this。
没有。如果捕获了变量,则将其捕获。该链接并非真正"讨论"那;唯一的答案证实了这种情况,标准中有适当的措辞。
lambda3
使用隐式捕获但身体提到可复制。这是否构成了可复制的 odr-use ?
是。 odr-use 的定义是
名称显示为可能已评估的表达式的变量是 odr-used ,除非它是满足出现在常量表达式中的要求的对象,并且lvalue-to-rvalue转换是立即的应用。
并且异常不适用,因为它不是常数(因此不能出现在常量表达式中)。 (但请注意,这是不正确的,因为没有默认捕获。)
lambda4
使用隐式捕获并强制使用另一个volatile副本。我确信这实际上会有效,但它的副本数量超过了最低限度。
实际上;您通过使用该值强制进行隐式捕获,并强制执行额外的复制。这是不必要的,因为lambda2
可以满足您的需求。