c++ 如何高效地返回std::optional

a8jjtwal  于 2023-01-22  发布在  其他
关注(0)|答案(1)|浏览(218)

我想问一下如何高效地返回一个std::optional,我想使用std::make_optional()。例如,让我们有这样的代码片段:

std::optional<Path> CreateCanonicalPath(const std::string_view& path)
{
  std::error_code errorCode;
  const auto result = std::filesystem::weakly_canonical(std::filesystem::u8path(path), errorCode);
  return !errorCode ? std::make_optional(result) : std::nullopt;
}

我特别感兴趣的是resultstd::make_optional的传递是否有优化,使用std::make_optional(std::move(result))会不会更好?
result是一个局部变量,但它并不完全在一个返回语句中,所以我假设编译器不能自己使用move。

bvjveswy

bvjveswy1#

有一个明显的改进:

std::optional<Path> CreateCanonicalPath(const std::string_view& path)
{
  std::error_code errorCode;
  auto result = std::filesystem::weakly_canonical(std::filesystem::u8path(path), errorCode);
  return !errorCode ? std::make_optional(std::move(result)) : std::nullopt;
}

创建临时对象const需要使用复制构造作为示例化返回的std::optional的一部分。
在此之后,任何进一步的改进都将在很大程度上取决于编译器的行为。这是不太可能的,但如果进行基准测试,可以观察到一些小的性能差异与替代语法,例如:

std::optional<Path> CreateCanonicalPath(const std::string_view& path)
{
  std::error_code errorCode;
  auto result = std::make_optional(std::filesystem::weakly_canonical(std::filesystem::u8path(path), errorCode));

  if (errorCode)
     result.reset();

  return result;
}

如果确定编译器会选择取消拷贝,这是NVRO允许的,那么也值得对此进行基准测试,但只有实际的基准测试才会产生有用的结果。

相关问题