【发布时间】:2019-08-16 07:42:38
【问题描述】:
假设我正在做一个涉及创建一个我不会修改的临时对象的计算:
auto tmp = val * val;
// Do some calculations with tmp...
此外,我不需要 tmp 成为左值,因为我不会获取它的地址。
在这些条件下,我应该在我的代码中使用哪个成语:
1. auto tmp = val * val;
2. const auto tmp = val * val;
3. const auto & tmp = val * val;
4. auto && tmp = val * val;
5. const auto && tmp = val * val;
请注意,我明确放弃了auto &,因为这通常会导致 UB。但是,我知道const auto & 会延长临时生命周期,所以我把它作为一个选项留在这里。
不出所料,对于这个简单的示例,-O3 无论如何都会编译成相同的代码:https://godbolt.org/z/oXj3hd
但在一个更复杂的例子中,我想他们不会。
我的想法是选项 3 或 5 可能是最正确的,因为它们将保留对象的常量性,并且因为它们将保存临时对象。
编辑:
很多人都提到,在这个简单的示例中,甚至不需要命名 temp。那是正确的。我所追求的是当生成temp的表达式很复杂时如何做的建议,并且会在代码中重复使用。
【问题讨论】:
-
您需要的实际计算有多复杂?如果它和
val * val一样简单,为什么不能在最终表达式中直接使用它(否则会使用tmp)? -
请注意,您不能移动
const对象。 -
你应该忘记。编译器足够聪明,可以删除所有内容。如果您确实有cpu消耗问题,请测量!但是您可以相信,每个普通编译器都不会出现临时问题!改为编写可读代码!您的示例充满了或多或少可怕的编码示例 :-) 顺便说一句:“几乎自动”将让您在未来度过一些不眠之夜。
-
我推荐stackoverflow.com/questions/13230480/what-does-auto-tell-us,其中的答案涵盖了这组选项,但它是否真的是一个骗子是值得怀疑的(问题在于解决方案,而不是问题)。
-
最后,请注意,这个问题的答案确实(必然)取决于使用的
operator*(即在一个理智的世界中按值返回的函数)。如果你想存储例如getter 的返回值(可能返回const&),或者在模板化设置中工作,在这种设置中你不能确定从某些计算中得到了什么,事情可能再次看起来不同。