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