Skip to content

Latest commit

 

History

History
42 lines (31 loc) · 2.27 KB

File metadata and controls

42 lines (31 loc) · 2.27 KB

In C++, use exchange or swap with nullopt to move out of std::optional - Keunwoo Lee's Minimum Viable Homepage

TL;DR

使用std::exchange可安全转移std::optional的值并将其置为nullopt,避免残留engaged状态引发未定义行为。单纯移动对象或其值会导致原对象仍显示有效但内部为空,需手动.reset()修复,但不如exchange直接。优先选用exchange确保安全简洁;仅在性能敏感场景考虑std::swap,但需注意代码可读性。测试表明exchangeswap能有效重置原optional,其他方法不可取。

Summary

  1. 推荐做法
    使用std::exchangestd::optional交换为std::nullopt以安全转移值:
  • auto dest = std::exchange(src, std::nullopt);
  • src变为nullopt,表达式返回原optional的值;若原值非空,可直接通过.value()*获取。
  • 类似Rust的Option::take方法。

替代方案std::swap需预先声明变量(如swap_dest),虽可能因特例化优化更高效,但可读性较差:

  • std::swap(swap_src, swap_dest);
  1. 错误用法及问题
  • 仅移动std::optional
    auto only_moved_to = std::move(moved_from_optional);
    • moved_from_optional仍处于“已移动(engaged)”状态(has_value()为真),内部值为空或未定义,易引发逻辑错误。
  • 仅移动内部值
    auto moved_value = std::move(moved_from_value.value());
    • 同样导致原optional保持engaged状态,需额外手动调用.reset()修正。
  1. 补救措施
  • 移动后追加.reset()
    move_then_reset.reset();
    • 虽可使原optional变为nullopt,但不如std::exchange简洁直接。
  1. 注意事项
  • 移动后原optional若未显式置为nullopt,残留engaged状态可能引发未定义行为(如误用.value())。
  • std::exchange是更安全且简洁的解决方案,优先选择;仅在性能敏感场景评估std::swap
  1. 附录验证代码
    完整示例代码输出显示:
  • exchangeswap后原optional变为nullopt
  • 直接移动或仅移值后原optional仍非空,内部值为空字符串。