【发布时间】:2012-05-22 13:10:06
【问题描述】:
假设我们有一个结构,用于保存 3 个带有一些成员函数的双精度:
struct Vector {
double x, y, z;
// ...
Vector &negate() {
x = -x; y = -y; z = -z;
return *this;
}
Vector &normalize() {
double s = 1./sqrt(x*x+y*y+z*z);
x *= s; y *= s; z *= s;
return *this;
}
// ...
};
为了简单起见,这有点做作,但我相信你同意类似的代码已经存在。这些方法允许您方便地链接,例如:
Vector v = ...;
v.normalize().negate();
甚至:
Vector v = Vector{1., 2., 3.}.normalize().negate();
现在,如果我们提供了 begin() 和 end() 函数,我们可以在新样式的 for 循环中使用我们的 Vector,比如循环 3 个坐标 x、y 和 z(毫无疑问,您可以构造更多"有用的”示例,通过将 Vector 替换为例如字符串):
Vector v = ...;
for (double x : v) { ... }
我们甚至可以这样做:
Vector v = ...;
for (double x : v.normalize().negate()) { ... }
还有:
for (double x : Vector{1., 2., 3.}) { ... }
但是,以下(在我看来)被破坏了:
for (double x : Vector{1., 2., 3.}.normalize()) { ... }
虽然这似乎是前两种用法的逻辑组合,但我认为最后一种用法会创建一个悬空引用,而前两种完全没问题。
- 这是否正确并广受赞赏?
- 以上哪一部分是“坏”部分,应该避免?
- 是否可以通过更改基于范围的 for 循环的定义来改进语言,以便在 for 表达式中构造的临时对象在循环期间存在?
【问题讨论】:
-
出于某种原因,我记得之前有人问过一个非常相似的问题,但忘记了它叫什么。
-
我认为这是一种语言缺陷。临时对象的生命周期不会扩展到整个 for 循环体,而只是用于设置 for 循环。不仅范围语法受到影响,经典语法也受到影响。在我看来,init 语句中的临时变量的生命周期应该延长到循环的整个生命周期。
-
@edA-qamort-ora-y:我倾向于同意这里潜藏着一个轻微的语言缺陷,但我认为特别是当你直接绑定一个临时的时,生命周期的延长会隐含地发生参考,但在任何其他情况下都没有 - 这似乎是临时生命周期潜在问题的半生不熟的解决方案,尽管这并不是说更好的解决方案是显而易见的。在构建临时文件时,可能是一个明确的“生命周期扩展”语法,这使得它一直持续到当前块的末尾——你怎么看?
-
@edA-qamort-ora-y: ...这相当于将临时对象绑定到引用,但优点是对读者来说更明确,即“终身延长”正在发生,内联(在表达式中,而不需要单独声明),并且不需要您命名临时。
标签: c++ for-loop c++11 language-lawyer foreach