Изменился ли стандарт C++ в отношении использования неопределенных значений и неопределенного поведения в C++14?
как описано в разделе инициализация влечет за собой преобразование lvalue-to-rvalue? Это int x = x; UB? в стандарте C++ есть удивительный пример в разделе 3.3.2пункт декларации, в котором int инициализируется собственным неопределенным значением:
int x = 12;
{ int x = x; }
здесь второй x инициализируется своим собственным (неопределенным) значением.
- пример]
какой ответ Йоханнеса на этот вопрос указывает на это неопределенное поведение, так как он требует это значение lvalue-на-правосторонним значением преобразования.
в последнем проекте стандарта C++14 N3936 где можно найти здесь этот пример изменился на:
unsigned char x = 12;
{ unsigned char x = x; }
здесь второй x инициализируется своим собственным (неопределенным) значением.
- пример]
что-то изменилось в C++14 в отношении неопределенных значений и неопределенного поведения, которое привело к этому изменению в например?
1 ответ:
Да, это изменение было вызвано изменениями в языке, что делает его неопределенное поведение если неопределенное значение создается путем оценки но с некоторыми исключениями для узкие символы без знака.
отчет о неисправности
1787чей предложенный текст можно найти в N39141 был недавно принят в 2014 году и включен в последний рабочий проектN3936:наиболее интересным изменением в отношении неопределенных значений будет раздел
8.5абзац 12 который идет от:если для объекта не указан инициализатор, объект инициализируется по умолчанию; если инициализация не выполняется, объект с автоматическим или динамическим временем хранения имеет неопределенное значение. [ Примечание: объекты со статической или потоковой длительностью хранения инициализируются нулем, см. 3.6.2. - на]
to (выделено мной):
если для объекта не указан инициализатор, то объект по умолчанию-инициализировать. Когда хранение для объекта с автоматическим или получена динамическая длительность хранения, объект имеет неопределено значение, и если инициализация объекта не выполняется, то объект сохраняет неопределенное значение до тех пор, пока это значение не будет заменено (5.17 [выражение.задница.)] [Примечание: объекты со статическим или потоковым хранилищем длительность инициализируется нулем, см. 3.6.2 [basic.начать.инициализация.] -конец Примечание] если оценка дает неопределенное значение, то поведение не определено, за исключением следующих случаев:
если неопределенное значение беззнакового узкого символьного типа (3.9.1 [basic.фундаментальные]) производится путем оценки:
второй или третий операнд условного выражения (5.16 [expr.cond]),
правый операнд запятой (5.18 [expr.запятая]),
операнд приведения или преобразования в беззнаковый узкий символьный тип (4.7 [conv.Интеграл], 5.2.3 [выраж.тип.conv], 5.2.9 [выражение.статический.cast], 5.4 [expr.литой]), или
выражение отброшенного значения (пункт 5 [expr]),
тогда результат операция-это неопределенное значение.
если неопределенное значение беззнакового узкого символьного типа (3.9.1 [basic.фундаментальные]) производится путем оценки права операнд простого оператора присваивания (5.17 [expr.осел]) чей первый операнд lvalue-выражение без знака узкая тип героя, неопределенное значение заменяет значение объекта, на который ссылается левый операнд.
если неопределенный значение типа unsigned узкая тип персонажа (3.9.1 [основная.фундаментальные]) производится путем оценки выражение инициализации при инициализации объекта без знака узкий тип символа, этот объект инициализируется неопределенным значение.
и следующий пример:
[ пример:
int f(bool b) { unsigned char c; unsigned char d = c; // OK, d has an indeterminate value int e = d; // undefined behavior return b ? d : 0; // undefined behavior if b is true }-пример ]
мы можем найти этот текст в N3936, который является действующим рабочий проект и
N3937- этоC++14 DIS.до C++1y
интересно отметить, что до этого проекта в отличие от c который всегда имел четко определенное представление о том, что использование неопределенных значений было неопределенным C++ использовал термин неопределенное значение, даже не определяя его (предполагая, что мы не можем заимствовать определение из C99) и см. отчет о дефекте 616. Мы должны были полагаться на недостаточно определенное преобразование lvalue-to-rvalue, который в проект стандарта C++11 рассматривается в разделе
4.1преобразование Lvalue-to-rvalue абзац 1 он говорит:[...]если объект неинициализирован, программа, которая требует этого преобразования имеет неопределенное поведение.[...]
Примечания:
1787ревизия отчет о дефекте 616, мы можем найти эту информацию в N3903
Comments