Можно ли оптимизировать часть условного выражения?

Рассмотрим следующий (немного сложный) цикл в C++:

using namespace std;

list<string> lst;
// Fill the list with some strings or keep it empty depending on something...

auto i = lst.begin(), e = lst.end();
string csv;
if (lst.size())
  do
    csv += *i;
  while(++i != e && (csv += ", ", true));

Цель этого состоит в том, чтобы сформировать строку, разделенную запятыми, состоящую из элементов исходного списка. И он правильно обрабатывает случай пустого списка. Но я сомневаюсь, что вторая часть условия while может быть оптимизирована каким-то (слишком) умным компилятором. Есть ли в стандарте пояснения по поводу таких случаев?

Я понимаю, что эту "задачу" можно решить разными способами, но я спрашиваю здесь не об алгоритме формирования CSV-строки.

Спасибо.

(csv += ", ", true) должен запускаться на каждой итерации, чтобы ++i != e не было ложью. В противном случае изменится наблюдаемое поведение кода, а это недопустимо.
NathanOliver 09.02.2023 14:19

Это UB, если список пуст, так как вы разыменовываете begin(), не проверяя сначала, не совпадает ли это с end()

perivesta 09.02.2023 14:19

@perivesta, Да, ты прав.

Serge Roussak 09.02.2023 14:21

@perivesta, я исправил UB.

Serge Roussak 09.02.2023 14:28

Я действительно изо всех сил пытаюсь понять, почему вы думаете, что это то, что компилятор может оптимизировать. Возможно, если бы вы объяснили больше своих мыслей по этому поводу, можно было бы дать лучшие ответы (и / или можно было бы найти более подходящий дубликат).

Cody Gray 09.02.2023 14:28

Вот способ сделать это с полностью определенным поведением: coliru.stacked-crooked.com/a/423a1661be110194

NathanOliver 09.02.2023 14:35
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Стандарт C++ допускает оптимизацию только в том случае, если она не имеет видимых эффектов.

В этом случае 2-я половина условия while не может быть полностью устранена, потому что это будет иметь наблюдаемый эффект. Компиляторы С++ не удалят его.

Чтобы быть педантичным, есть редкие случаи, когда оптимизация разрешена с наблюдаемым поведением (NRVO, новое выражение, исключения с плавающей запятой), см. правило «как если» для деталей.

Jarod42 09.02.2023 16:47

Оптимизациям не разрешается изменять поведение вашего кода. Таким образом, независимо от оптимизации, ваш код всегда будет делать то, что вы записали. Это предполагает, что ваш код является допустимым C++ и не имеет неопределенного поведения.

Что касается вашего фактического кода, я обычно рекомендую быть менее умным, чтобы его было легче понять и поддерживать:

std::string csv;
bool first = true;
for (std::string entry : lst) {
  if (!first) {
    csv += ", ";
  }
  first = false;
  csv += entry;
}

В отличие от вашего кода, это также будет правильно работать для пустых списков.

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