bit*_*ask 14 c++ const-correctness move-semantics c++17
我对本地范围内的任何对象的默认行为是 make it const。例如:
auto const cake = bake_cake(arguments);
Run Code Online (Sandbox Code Playgroud)
我尽量减少非功能性代码,因为这会增加可读性(并为编译器提供一些优化机会)。所以在类型系统中也反映这一点是合乎逻辑的。
然而,使用移动语义,这会产生问题:如果我cake很难或不可能复制并且我想在完成后将其传递出去怎么办?例如:
if (tastes_fine(cake)) {
return serve_dish(cake);
}
Run Code Online (Sandbox Code Playgroud)
据我了解复制cake省略规则,不能保证副本会被删除(但我不确定这一点)。
所以,我不得不搬出cake去:
return serve_dish(std::move(cake)); // this will not work as intended
Run Code Online (Sandbox Code Playgroud)
但这std::move不会有任何用处,因为它(正确地)不会转换Cake const&为Cake&&. 即使对象的生命周期已接近尾声。我们不能从我们承诺不会改变的东西中窃取资源。但这会削弱常量正确性。
那么,我怎样才能拥有我的蛋糕并吃掉它呢?
(即我怎样才能拥有常量正确性并从移动语义中受益。)
我相信从一个const对象中移动是不可能的,至少使用标准的移动构造函数和非mutable成员是不可能的。但是,可以有一个const自动本地对象并为其应用复制省略(即NRVO)。在您的情况下,您可以按如下方式重写原始函数:
Cake helper(arguments)
{
const auto cake = bake_cake(arguments);
... // original code with const cake
return cake; // NRVO
}
Run Code Online (Sandbox Code Playgroud)
然后,在您的原始函数中,您只需调用:
return serve_dish(helper(arguments));
Run Code Online (Sandbox Code Playgroud)
由于由 返回的对象helper已经是一个非常量值,因此可以将其移出(如果适用,可以再次省略)。
这是演示此方法的现场演示。请注意,在生成的程序集中没有调用复制/移动构造函数。