Как эффективно вернуть std::Optional

Я хотел бы спросить, как эффективно вернуть 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;
}

Меня особенно интересует, есть ли какая-то оптимизация при переходе result в std::make_optional. Может лучше использовать std::make_optional(std::move(result))?

И предотвращает ли это какие-либо РВО или НВРО? result — это локальная переменная, но она не совсем в операторе возврата, поэтому я предполагаю, что компилятор не может использовать перемещение сам по себе.

Что-то связанное: youtu.be/dGCxMmGvocE?t=430

Ranoiaetep 20.01.2023 10:28

Вы создали какие-то измерения (эталонные тесты)? Как вы думаете, почему этот код нужно оптимизировать? Это дикая догадка, или вы профилировали свой производственный код, чтобы обнаружить узкие места? Из всего этого weakly_canonical будет самой медленной частью, так как взаимодействует с ОС.

Marek R 20.01.2023 10:42

Какой смысл заворачивать std::path в std::optional? В чем разница между возвращенным пустым optional и пустым path в случае ошибок? Насколько я знаю, optional используется в основном для типов, которые сами по себе не предоставляют «пустое» состояние (например, целые числа) или где пустое состояние может быть допустимым результатом (например, с std::string).

Daniel Langr 20.01.2023 11:50

@DanielLangr: пустой путь не обязательно является недопустимым путем. Это действительный результат разрезания пути, объединения и нормализации, дифференцирования и т. д. Я не думаю, что это обязательно указывает на ошибку. Но у меня нет большого опыта с std::filesystem.

Jiří Lechner 20.01.2023 13:49

@JiříLechner Я тоже, но то, что ты пишешь, имеет смысл.

Daniel Langr 20.01.2023 16:15

Почему вы хотите использовать make_Optional()? Это как-то мешает.

Michaël Roy 22.01.2023 01:36

@MichaëlRoy, make_optional() - это заводской шаблон, он может позволить использовать некоторые оптимизации. Например, make_shared() делает это, и это довольно важно. Я не думаю, что это относится к make_optional(), но мне нравится, чтобы это соответствовало другим make_...() функциям.

Jiří Lechner 23.01.2023 12:00

@JiříLechner Это может позволить некоторую оптимизацию, но не в этом случае, так как это добавит std::Optional присваивание перемещения и, таким образом, отменит оптимизацию возврата на место.

Michaël Roy 23.01.2023 17:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
8
519
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть одно очевидное улучшение:

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, то это также стоит протестировать. Но только реальный бенчмаркинг даст полезные результаты.

Таким образом, во втором фрагменте будет использоваться семантика перемещения, поскольку функция возвращает локальную переменную. А в зависимости от компилятора может применяться даже NVRO.

Jiří Lechner 20.01.2023 13:40

Другие вопросы по теме