Строгое правило сглаживания и сглаживание типов в C++
Я пытаюсь понять неопределенное поведение при нарушении строгого правила сглаживания. Я прочитал много статей о SO, чтобы понять это. Однако остается один вопрос:я действительно не понимаю, когда два типа нелегального псевдонима. cpp-ссылка гласит:
тип антиалиасинга
всякий раз, когда делается попытка прочитать или изменить сохраненное значение объекта типа DynamicType через glvalue типа AliasedType, поведение не определено, если не выполняется одно из следующих действий:
- AliasedType и DynamicType похожи.
- AliasedType - это (возможно, CV-квалифицированный) подписанный или неподписанный вариант DynamicType.
- AliasedType - std:: byte, (начиная с C++17)char или unsigned char: это позволяет исследовать представление объекта любого объекта в виде массива байтов.
Я также нашел хороший пример на SO где я четко вижу проблему:
int foo( float *f, int *i ) {
*i = 1;
*f = 0.f;
return *i;
}
int main() {
int x = 0;
std::cout << x << "n"; // Expect 0
x = foo(reinterpret_cast<float*>(&x), &x);
std::cout << x << "n"; // Expect 0?
}
int
и float
не являются подобными типами, и эта программа, возможно, наносит ущерб. Чего я не вижу и не понимаю, так это следующей модификации:
struct A
{
int a;
};
struct B
{
int b;
};
A foo( A *a, B *b ) {
a->a = 1;
b->b = 0;
return *a;
}
int main() {
A a;
a.a = 0;
std::cout << a.a << "n"; // Expect 0
a = foo(&a, reinterpret_cast<B*>(&a));
std::cout << a.a << "n"; // Expect 0?
}
Are A
и B
похожие типы и все в порядке, или они нелегально псевдонимы, и у меня неопределенное поведение. И если это законно, это потому, что A
и B
являются агрегатами (если да, то что бы у меня было изменить, чтобы сделать его неопределенным-поведение)?
любые хедз-ап и помощь были бы очень признательны.
редактировать по вопросу о дублировании
Я в курсе этой пост, но я не вижу, где они уточняют, какие типы похожи. По крайней мере, до такой степени, чтобы я это понимал. Поэтому было бы любезно, если бы вы не закрывали этот вопрос.
2 ответов
нет, это не законно и у вас есть неопределенное поведение:
8.2.1 категория значений [basic.lval]
11 Если программа пытается получить доступ к сохраненным значением объекта через glvalue другого чем один из следующих типов поведение не определено:63
(11.1) - динамический тип объекта,
(11.2) - CV-квалифицированная версия динамического типа объекта,
(11.3) - типа (как определено в 7,5) в динамический тип объект,
(11.4) - тип со знаком или без знака, соответствующий динамический тип объекта,
(11.5) - тип со знаком или без знака, соответствующий cv-квалифицированная версия динамического типа объекта,
(11.6) - тип агрегата или объединения, который включает один из вышеупомянутые типы среди его элементов или нестатических элементов данных (включая рекурсивно элемент или нестатический элемент данных субагрегатный или замкнутый Союз),
(11.7) - тип, который является (возможно, CV-квалифицированным) типом базового класса динамический тип объекта,
(11.8) - символ, беззнаковый символ или std::тип байта
63) цель этого списка-указать те обстоятельства, при которых объект может иметь или не иметь псевдонимов.
в выражении b->b = a;
неопределенное поведение связано не с назначением, а с выражением доступа члена класса,b->b
. Если бы это выражение не было UB, ваш код не был бы UB.
на [expr.ref] / 1 указывается, что член класса access constitue доступ к объекту b
(слева от ->):
постфиксное выражение, за которым следует точка . или стрелка ->, необязательно с последующим шаблоном ключевого слова ([температура.names]), а затем следует id-выражение, является постфиксным выражением. вычисляется постфиксное выражение перед точкой или стрелкой; [67] результат этой оценки вместе с id-выражением определяет результат всего постфиксного выражения.
[67] если вычисляется выражение доступа члена класса, оценка подвыражения происходит, даже если результат не нужен для определения значения всего постфиксного выражения, например, если id-выражение обозначает статический член.
смелый шахте
так b->b
прочитайте значение объекта a
с выражением типа B
и правило, которое вы цитируете, относится сюда.