Разрешено ли компилятору оптимизировать dynamic_cast изменчивого указателя, когда компилятор не видит возможный тип, который может выполнить приведение? - PullRequest
0 голосов
/ 28 сентября 2018

Посмотрите на этот маленький фрагмент:

struct A {
    virtual ~A() { }
};

struct B { };

bool fn() {
    A *volatile a = new A;
    return dynamic_cast<B *>(a); 
}

Разрешено ли компилятору полностью удалить dynamic_cast и преобразовать dynamic_cast в простое nullptr;?

Причинаэтого вопроса: ответ .

Примечания:

  • Предположим, что volatile означает, что компилятор не может предполагать что-либо о a, потому что этонеустойчивый.Вот вопрос почему.

  • Тот факт, что dynamic_cast не может быть удален, заключается в том, что где-то в программе может быть тип, который выводитот A и B.

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Да.dynamic_cast не имеет наблюдаемого поведения за пределами возвращаемого значения.

Компилятор знает о статическом типе, на который указывает a.

Таким образом, согласно правилу «как будто», компиляторможно свободно оценивать динамическое приведение во время компиляции.

Фактически:

struct A { virtual ~A() {} };
struct B:A {};

bool foo() {
  A* a = new A;
  return dynamic_cast<B*>(a);
}

приведенное выше выражение динамического приведения также можно оптимизировать до return false; new нельзя опускать без целыхоптимизация программы, поскольку кто-то может перегрузить глобальный оператор new;как только будет доказано, что ни один глобальный оператор new не перегружен, он может даже оптимизировать вызов на new A, поскольку ни выделение памяти по умолчанию operator new, ни создание A, ни его уничтожение не имеют видимых побочных эффектов.

0 голосов
/ 28 сентября 2018

Да, компилятор может опустить вызов dynamic_cast согласно правилу «как будто» 1) тогда и только тогда, когда он может доказать, что единственным действительным результатом вызова является false.Это просто.

Сложная задача - доказать, что единственным действительным результатом dynamic_cast является false.Вы можете доказать, что если в вашей программе нет класса, который наследовал бы от A и B.

Теперь я не очень разбираюсь в этой части, но я думаю, что вы можете сделать это, когда высоздать двоичный файл и иметь все типы в вашей программе, только если это исполняемый файл (не библиотека) и только если программа не динамически связывается с другими библиотеками.


1) dynamic_cast на указатели не имеет побочного эффекта, он не выбрасывает

...