В стандарте C ++ 14 (n3797) раздел о преобразованиях lvalue в rvalue выглядит следующим образом (выделено мной):
4.1 Преобразование Lvalue в rvalue [conv.lval]
Glvalue (3.10) нефункционального типа, не являющегося массивом
T
может быть преобразован в prvalue. ЕслиT
является неполным типом, программа, которая требует этого преобразования, плохо сформирована. ЕслиT
это тип, не относящийся к классу, тип prvalue — версия cv-unqualifiedT
, В противном случае тип значенияT
,Когда преобразование lvalue в rvalue происходит в неоцененном операнде
или его подвыражение (пункт 5) значение, содержащееся в
указанный объект не доступен. Во всех остальных случаях результат
Конверсия определяется по следующим правилам:
- Если
T
является (возможно, cv-квалифицированным)std::nullptr_t
тогда результат является константой нулевого указателя.- В противном случае, если
T
имеет тип класса, преобразование копирует-инициализирует временный типT
от glvalue и результат преобразования является prvalue для временного.- В противном случае, если объект, на который ссылается glvalue, содержит недопустимое значение указателя, поведение определяется реализацией.
- В противном случае, если
T
является (возможно, квалифицированным cv) типом без знака, и объект, на который ссылается glvalue, содержит неопределенное значение, и этот объект не имеет автоматической длительности хранения, или glvalue был операндом унарного&
оператор или он был привязан к ссылке, результатом является неопределенное значение.- В противном случае, если объект, на который ссылается glvalue, имеет неопределенное значение, поведение не определено.
- В противном случае объект, обозначенный glvalue, является результатом prvalue.
- [Замечания: Смотри также 3.10]
Каково значение этого абзаца (выделено жирным шрифтом)?
Если бы этот параграф не был здесь, то ситуации, в которых он применяется, привели бы к неопределенному поведению. Обычно я ожидаю, что доступ к unsigned char
Значение, пока оно имеет неопределенное значение, ведет к неопределенному поведению. Но с этим пунктом это означает, что
&
или привязать его к ссылке, илиunsigned char
не имеет автоматической продолжительности хранения,тогда преобразование дает неопределенное значение, а не неопределенное поведение.
Правильно ли я пришел к выводу, что эта программа:
#include <new>
#include <iostream>
// using T = int;
using T = unsigned char;
int main() {
T * array = new T[500];
for (int i = 0; i < 500; ++i) {
std::cout << static_cast<int>(array[i]) << std::endl;
}
delete[] array;
}
четко определен стандартом и должен выводить последовательность из 500 неопределенных целых чисел, тогда как та же программа, в которой T = int
будет иметь неопределенное поведение?
IIUC, одна из причин сделать UB для чтения вещей с неопределенными значениями, заключается в том, чтобы оптимизатор мог агрессивно удалять мертвые хранилища. Таким образом, этот абзац может означать, что соответствующий компилятор не может делать столько оптимизации при работе с unsigned char
или массивы unsigned char
,
Предполагая, что я правильно понимаю, в чем смысл этого правила? Когда полезно читать unsigned char
которые имеют неопределенные значения и получают неопределенные результаты вместо UB? У меня такое чувство, что, если они приложат столько усилий для разработки этой части правила, у них будет мотивация помочь определенным примерам кода, которые им интересны, или будут соответствовать какой-то другой части стандарта, или упростить какую-то другую проблему. , Но я понятия не имею, что это может быть.
Во многих ситуациях код записывает некоторые части PODS или массива без записи всего, а затем использует такие функции, как memcpy
или же fwrite
скопировать или записать всю вещь, не обращая внимания на то, какие части имеют присвоенные значения, а какие нет. Хотя в коде C ++ не очень распространено использование байтовых операций для копирования или записи содержимого агрегатов, возможность сделать это является фундаментальной частью языка. Требование, чтобы программа записывала определенные значения во все части объекта, включая те, которые ни о чем не будут «заботиться», без необходимости снизит эффективность.
Других решений пока нет …