C++, возникнет ли неопределенное поведение в следующем случае

103
16 декабря 2021, 04:00

Подскажите, пожалуйста, возникает ли в следующем случае неопределенное поведение:

void do_something(const Object& _1,
                  const Object& _2,
                        Object& _3)
{
    // ...
    for (size_t i = 0; i < ...; ++i)
    {
        const auto value = _1[i] + _2[i];
        _3[i] = value;
    }
}
int main(int argc, char **argv)
{
    Object _1;
    Object _2;
    do_something(_1, _2, _1);
    return 0;
}

С одной стороны, здесь нет нарушения Правила Строгих Псевдонимов.

Но с другой стороны, внутри функции do_something() мы меняем состояние внешнего объекта, на который ссылается функция, как на константный.

Мой код ведет себя странно.

Причем, если я сделаю так:

int main(int argc, char **argv)
{
    Object _1;
    Object _2;
    Object _3;
    do_something(_1, _2, _3);
    return 0;
}

То проблема исчезает.

Answer 1

Если в коде ваши обьекты верно инициализированы(в функции нет выхода за пределы последовательностей, то не будет никакого неопределенного поведения. В данном случаи константными являются только аргументы функции, а передаваемые ей обьекты вполне могут быть неконстантными. Константность аргументов говорит о том, что функция не модифицирует первые два аргумента. Но третьим аргументом может выступать любой передаваемый неконстантный обьект, в том числе и один из двух переданных обьектов.

P.S. Вот какой код выполняется у вас:

int main(int argc, char **argv)
{
    Object a;
    Object b;       
    {
        const Object& _1 = a;
        const Object& _2 = b;
        Object& _3 = a;
        // ...
        for (size_t i = 0; i < ...; ++i)
        {
             const auto value = _1[i] + _2[i];
            _3[i] = value;
        }
    } //конец функции
    return 0;
}

обьект можно без проблем модифицировать через ссыльку _3

Answer 2

Если какой-то объект виден через константный путь доступа, это совсем не означает, что он не может меняться. Он может меняться через другие, неконстантные пути доступа. Именно это и происходит у вас в коде. Никакого неопределенного поведения в этом нет даже отдаленно.

Компилятор никогда не будет делать никаких оптимизаций на основе константности пути доступа, если у него нет стопроцентной уверенности в том, что объект не может поменяться через другие пути доступа. В языке С вы можете придать ему такую уверенность вручную, при помощи спецификатора restrict. В С++ такого спецификатора официально нет.

Зачем вы вынесли упоминание "правила строгих псевдонимов" в заголовок - не ясно тоже. Никакого отношения к "правилу строгих псевдонимов" данная ситуация не имеет.

READ ALSO
Почему не выводятся нужные слова?

Почему не выводятся нужные слова?

Имеется такая задача

241
Как вычислить скорость загрузки файла через QNetworkAccessManager

Как вычислить скорость загрузки файла через QNetworkAccessManager

Попробовал так, но не получил адекватных значений

82
c++ Нужно оптимизировать задачу

c++ Нужно оптимизировать задачу

задания YandexContest: Даны массив А и В

91