假设我正在做一个涉及创建一个我不会修改的临时对象的计算:
auto tmp = val * val;
// Do some calculations with tmp...
Run Code Online (Sandbox Code Playgroud)
此外,我不需要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;
Run Code Online (Sandbox Code Playgroud)
请注意,我明确地放弃了,auto &因为这通常会导致UB。但是,我知道const auto &可以延长temp的寿命,因此在此我将其保留为一种选择。
不出所料,对于这个简单的示例,-O3无论如何都会编译为相同的代码:https : //godbolt.org/z/oXj3hd
但是在一个更复杂的示例中,我想他们不会。
我的想法是,选项3或5可能是最正确的,因为它们将保留对象的恒定性,并且将保留临时对象。
编辑:
许多人提到了一个事实,在这个简单的示例中,甚至不需要命名临时文件。那是正确的。我所追求的是关于生成临时表达式的复杂操作的建议,并将在代码中重复使用。
为什么要绑定引用val * val?除了性能,我认为这是一种混淆。
毫不奇怪,对于这个简单的示例,-O3始终会编译为相同的代码:
是的,这里没有什么大的惊喜。因此,只需使用最简洁,最不人为。const不是为了性能,编译器足够聪明,可以意识到在没有您帮助的情况下就不会修改变量,尽管可以const为您记录常量,从而增加了可读性。因此
const auto tmp = val * val;
Run Code Online (Sandbox Code Playgroud)
其他任何事情都将简单的事情变成不必要的复杂事情。
最后但并非最不重要的一点是,考虑是否根本需要临时文件,或者是否可以简单地val*val代替编写tmp。另一方面,如果您使用了tmp很多次,那么给它起一个有意义的名称当然是值得的(有意义=比tmp;更有意义的东西)
附注:请注意,const不要偏离tmp,这可能会对性能造成不利影响。但是,通常,在担心性能时,应首先编写可读代码,然后再衡量性能。
auto tmp = val * val;
Run Code Online (Sandbox Code Playgroud)
如果您想tmp稍后在(std::move(tmp))上强制转换为右值,请使用此选项。
const auto tmp = val * val;
Run Code Online (Sandbox Code Playgroud)
当您不需要std::move(tmp)以后使用此功能时。明确,毫不奇怪地授予Scott Meyers项目“ const尽可能使用”的荣誉。
const auto & tmp = val * val;
Run Code Online (Sandbox Code Playgroud)
不要这样 它确实延长了生命周期,但是与2相比,您没有任何收获,因为对象无论如何都必须生活在某个地方。当val*val收益率的值的对象,你会不会跟2.复制因(N)静脉阻塞(假设operator *为val三立对象的行为),所以const auto& tmp并const auto tmp都将引用一个对象的范围的堆内。
auto && tmp = val * val;
const auto && tmp = val * val;
Run Code Online (Sandbox Code Playgroud)
不会产生任何性能上的好处,但是会使代码的读取复杂化。不要这样
| 归档时间: |
|
| 查看次数: |
138 次 |
| 最近记录: |