我对本地范围内的任何对象的默认行为是使其const
. E.g.:
auto const cake = bake_cake(arguments);
我尝试尽可能少地使用非功能代码,因为这可以提高可读性(并为编译器提供一些优化机会)。因此,在类型系统中也反映这一点是合乎逻辑的。
然而,使用移动语义,这会产生问题:如果我的cake
很难或不可能复制,我想在完成后将其分发出去?例如。:
if (tastes_fine(cake)) {
return serve_dish(cake);
}
我认为复制省略规则 https://en.cppreference.com/w/cpp/language/copy_elision不能保证cake
副本将被删除(但我不确定这一点)。
所以,我必须搬家cake
out:
return serve_dish(std::move(cake)); // this will not work as intended
但那个std::move
will 不做任何有用的事情 https://gcc.godbolt.org/z/YHFqtm,因为它(正确地 https://stackoverflow.com/q/10770181/430766) 不会投射Cake const&
to Cake&&
。即使对象的生命周期已接近尾声。我们不能从我们承诺不改变的事物中窃取资源。但这会削弱常量正确性。
那么,怎样才能鱼与熊掌兼得呢?
(即我怎样才能拥有常量正确性并从移动语义中受益。)
我相信不可能从const
对象,至少有一个标准的移动构造函数和非mutable
成员。然而,有可能有一个const
自动本地对象和apply 复制省略 https://stackoverflow.com/q/14429988/580083(即NRVO) 为了它。对于您的情况,您可以按如下方式重写原始函数:
Cake helper(arguments)
{
const auto cake = bake_cake(arguments);
... // original code with const cake
return cake; // NRVO
}
然后,在您的原始函数中,您可以调用:
return serve_dish(helper(arguments));
由于返回的对象是helper
已经是非常量右值,它可能会被移出(如果适用,可能会再次被省略)。
Here https://godbolt.org/z/QbvXx7是演示这种方法的现场演示。请注意,生成的程序集中没有调用复制/移动构造函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)