Строгое правило сглаживания и сглаживание типов в 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 и правило, которое вы цитируете, относится сюда.