C++0x:Lambda 按值捕获,始终是副本?
编译器是否允许消除按值捕获所需的副本?
vector<Image> movie1;
apply( [=movie1](){ return movie1.size(); } );
- 有没有什么情况编译器不需要复制
movie1
?- 也许如果编译器知道,
apply
实际上不会改变movie1
? - 或者在任何情况下 Lambda 都默认为
const
函子,这是否有帮助?
- 也许如果编译器知道,
vector
有一个移动构造函数和移动赋值,这对完全有帮助吗?- 如果是,是否也需要将这些添加到
Image
中,以防止此处出现昂贵的副本?
- 如果是,是否也需要将这些添加到
- 与按值参数捕获相比,按值捕获何时以及如何需要副本的机制是否存在差异?例如。
void opera(vector movie)
?
Is the compiler allowed to eliminate the copy that is required for the by-value capture?
vector<Image> movie1;
apply( [=movie1](){ return movie1.size(); } );
- Is there any circumstance that the compiler does not need to copy
movie1
?- Maybe if the compiler could know, that
apply
does not actually changemovie1
? - Or does it help that Lambdas are by default
const
functors in any case?
- Maybe if the compiler could know, that
- Does it help at all that
vector
has a move constructor and move assign?- If yes, is it required to add these to
Image
as well, to prevent an expensive copy here?
- If yes, is it required to add these to
- Is there a difference in the mechanism when and how a copy is required for by-value capture compared to by-value arguments? eg.
void operate(vector<Image> movie)
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
“假设”规则总是。只要看起来好像遵循了规则,编译器就可以做任何它喜欢做的事情。因此,对于复制构造函数和析构函数没有副作用的对象,并且没有对副本进行任何更改,或者之后不访问原始对象(因此如果我们对对象进行更改,没有人会注意到),编译器可以证明根据“假设”规则消除副本是合法的。
但除此之外,不,正如@Ben 所说,它不能仅仅消除副本。 “常规”复制省略规则不涵盖这种情况。
There is always the "as-if" rule. As long as it looks as if the rules had been followed, the compiler can do whatever it likes. So for objects where the copy constructor and destructor have no side effects, and where no changes are made to the copy, or the original object isn't accessed afterwards (so no one will notice if we make changes to the object), the compiler could prove that eliminating the copy is legal under the "as-if" rule.
But other than that, no, it can't just eliminate the copy, as @Ben said. The "regular" copy elision rules don't cover this case.
我相当肯定它不能。
即使外部函数不再显式使用该变量,移动该变量也会改变破坏的语义。
为
Image
提供移动构造函数并没有帮助,vector
可以移动
或交换
而不移动其元素。如果变量从现在开始是只读的,为什么不通过引用捕获呢?您甚至可以创建一个常量引用并捕获它。
如果变量不是只读的,则需要副本。无论外部函数还是 lambda 执行修改,编译器都不能允许该修改对另一个函数可见。
我发现按值捕获和按值参数传递之间的唯一区别是捕获是命名的,它不能是临时的。因此不能使用适用于临时变量的参数传递优化。
I'm fairly sure it cannot.
Even if the outer function no longer explicitly uses the variable, moving the variable would change the semantics of destruction.
Having move constructors for
Image
doesn't help, avector
canmove
orswap
without moving its elements.If the variable is read-only from this point forward, why not capture by reference? You could even create a const reference and capture that.
If the variable is not read-only, the copy is required. It doesn't matter whether the outer function or the lambda performs the modification, the compiler cannot allow that modification to become visible to the other.
The only difference I see between by-value capture and by-value argument passing is that the capture is named, it cannot be a temporary. So argument passing optimizations applicable to temporaries cannot be used.