Демонстрирует ли выражение цепочки std::string в коде Бьярна Страуструпа неопределенное поведение?
В книге Бьярна Страуструпа «Язык программирования C», 4-е издание фрагмент кода иллюстрирует цепочку с использованием метода replace std::string:
void f2() {
std::string s = "but I have heard it works even if you don't believe in it";
s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
assert(s == "I have heard it works only if you believe in it");
}
Однако этот код демонстрирует неопределённое поведение вместо вызова неопределенного поведения.
Причина такого неопределённого поведения кроется в порядке вычислений, который не определён для подвыражения связанных вызовов функций. В этом случае вызовы функции s.find оцениваются либо до, либо после первого вызова s.replace, изменяя длину результирующей строки и влияя на результат последующего вызова find.
Пример в вопросе демонстрирует это: при оценке разными компиляторами (clang, gcc) из-за разного порядка оценки получаются разные результаты. цепочка вызовов функций вводит порядок вычислений слева направо для каждого вызова функции, аргументы каждого вызова упорядочиваются только перед
относительноэтого конкретного вызова функции.В этом примере эта неопределенность возникает при оценке s.find("even") и s.find("do not") относительно s.replace(0, 4, "").
Игнорируя дальнейшие подпункты -разбивку выражений, последовательность шагов вычисления и их взаимозависимость можно изобразить следующим образом:Шаг 1: s.replace(0, 4, "") // A Шаг 2: s.find("даже") // B Шаг 3: s.replace(B, 4, «только») // C Шаг 4: s.find("не делать") // D Шаг 5: s.replace(D, 6, "") // E
Хотя A упорядочивается перед B, который, в свою очередь, упорядочивается перед C, между ними
нет отношения последовательностиB и D относительно A. В результате D можно оценивать либо до, либо после A, что приводит к разным результатам в зависимости от выбранной последовательности.
Step 1: s.replace(0, 4, "") // A Step 2: s.find("even") // B Step 3: s.replace(B, 4, "only") // C Step 4: s.find("don't") // D Step 5: s.replace(D, 6, "") // EC 17 Изменения
Стандарт C 17 усиливает порядок правил оценки постфиксных выражений и их списка выражений, обеспечивая четко определенное поведение рассматриваемого кода. Последовательность следующая:
Постфиксное-выражение упорядочивается перед каждым выражением в списке выражений.
Инициализация каждого параметра имеет неопределенную последовательность по отношению к инициализации любого параметра. другой параметр.Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3