Рассмотрим следующий (немного сложный) цикл в 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-строки.
Спасибо.
Это UB, если список пуст, так как вы разыменовываете begin(), не проверяя сначала, не совпадает ли это с end()
@perivesta, Да, ты прав.
@perivesta, я исправил UB.
Я действительно изо всех сил пытаюсь понять, почему вы думаете, что это то, что компилятор может оптимизировать. Возможно, если бы вы объяснили больше своих мыслей по этому поводу, можно было бы дать лучшие ответы (и / или можно было бы найти более подходящий дубликат).
Вот способ сделать это с полностью определенным поведением: coliru.stacked-crooked.com/a/423a1661be110194





Стандарт C++ допускает оптимизацию только в том случае, если она не имеет видимых эффектов.
В этом случае 2-я половина условия while не может быть полностью устранена, потому что это будет иметь наблюдаемый эффект. Компиляторы С++ не удалят его.
Чтобы быть педантичным, есть редкие случаи, когда оптимизация разрешена с наблюдаемым поведением (NRVO, новое выражение, исключения с плавающей запятой), см. правило «как если» для деталей.
Оптимизациям не разрешается изменять поведение вашего кода. Таким образом, независимо от оптимизации, ваш код всегда будет делать то, что вы записали. Это предполагает, что ваш код является допустимым C++ и не имеет неопределенного поведения.
Что касается вашего фактического кода, я обычно рекомендую быть менее умным, чтобы его было легче понять и поддерживать:
std::string csv;
bool first = true;
for (std::string entry : lst) {
if (!first) {
csv += ", ";
}
first = false;
csv += entry;
}
В отличие от вашего кода, это также будет правильно работать для пустых списков.
Альтернативные способы идиомы-для-итерации-между-каждой-последовательной-парой-элементовs.
(csv += ", ", true)должен запускаться на каждой итерации, чтобы++i != eне было ложью. В противном случае изменится наблюдаемое поведение кода, а это недопустимо.