为何NRVO在结构化绑定场景下无法生效?
核心问题部分
请参考以下示例代码:
#include <iostream> struct movable { movable() { std::cout << "movable()\n"; } movable(movable&&) noexcept { std::cout << "movable(&&)\n"; } movable(const movable&) noexcept { std::cout << "movable(const &)\n"; } ~movable() { std::cout << "~movable()\n"; } }; movable rvo() { return {}; } movable nrvo() { movable m; return m; } movable cnrvo() { const movable m; return m; } movable binding_nrvo() { struct binding { movable m; }; auto [m] = binding{}; // explicit move is required // return std::move(m); // otherwise a copy would be made return m; } int main() { { std::cout << "rvo:\n"; movable m = rvo(); } { std::cout << "\nnrvo:\n"; movable m = nrvo(); } { std::cout << "\ncnrvo:\n"; movable m = cnrvo(); } { std::cout << "\nbinding_nrvo:\n"; movable m = binding_nrvo(); } return 0; }
使用-std=c++17 -O3编译后的输出如下:
rvo: movable() ~movable() nrvo: movable() ~movable() cnrvo: movable() ~movable() binding_nrvo: movable() movable(const &) ~movable() ~movable()
我了解NRVO对“包装”值无效,例如必须显式使用std::move(如return std::move(std::get<0>(tuple));)来避免拷贝。
但此处是按值绑定:auto [m] = binding{};,我认为m是独立对象,为何NRVO仍不生效?
背景说明部分
本问题并非聚焦此部分,仅作背景补充:
我尝试用结构化绑定实现类似Go语言的错误处理控制流,理想写法如下:
const auto [value, err] = getSome(); if (err) return err;
在没有expected类返回类型的情况下,这对我而言是无需异常的最简洁控制流。我原本期望const修饰的err能像cnrvo()示例那样触发NRVO,但实际并未生效。
而且由于必须使用std::move,value也无法设为const。最终写法变成了:
auto [value, errGetSome] = getSome(); // can't have several `err` in the scope if (!errGetSome) return std::move(errGetSome); // just promise not to modify `value` const auto& actualValue = value;
……这完全违背了初衷。
无论如何,我希望得到核心问题的解答。
内容的提问来源于stack exchange,提问作者Sergey Kolesnik
相关产品推荐
相关产品推荐

