C ++ 0x:为Lambda捕获值,总是一个副本?

时间:2011-03-12 14:33:25

标签: c++ c++11 copy-constructor lambda

是否允许编译器消除按值捕获所需的副本

vector<Image> movie1;
apply( [=movie1](){ return movie1.size(); } );
  • 是否存在编译器不需要复制movie1的情况?
    • 也许如果编译器可以知道,apply实际上不会改变 movie1
    • 或者,在任何情况下,Lambdas默认 const仿函数是否有帮助?
  • vector有一个移动构造函数移动分配,这对 有帮助吗?
    • 如果是,是否需要将这些内容添加到Image,以防止在此处出现昂贵的副本?
  • 按值参数相比,按值捕获需要副本的时间和方式是否存在差异?例如。 void operate(vector<Image> movie)

2 个答案:

答案 0 :(得分:9)

我很确定它不能。

即使外部函数不再显式使用变量,移动变量也会改变破坏的语义。

移动Image的构造函数没有帮助,vector可以moveswap而不移动其元素。

如果变量从此时开始是只读的,为什么不通过引用捕获?你甚至可以创建一个const引用并捕获它。

如果变量不是只读变量,则需要复制。无论外部函数还是lambda执行修改都无关紧要,编译器不能允许该修改对另一个进行修改。

我在 by-value capture by-value参数传递之间看到的唯一区别是捕获被命名,它不能是临时的。因此,不能使用适用于临时值的参数传递优化。

答案 1 :(得分:3)

总是“as-if”规则。只要它看起来好像遵循了规则,编译器就可以做任何喜欢的事情。因此,对于复制构造函数和析构函数没有副作用的对象,以及未对副本进行任何更改的对象,或者之后未访问原始对象(因此,如果我们对对象进行更改,则没有人会注意到),编译器可以证明根据“as-if”规则删除副本是合法的。

但除此之外,不,它不能只是消除副本,正如@Ben所说。 “常规”复制省略规则不包括此案例。