当编译器看不到可能满足强制转换的类型时,是否允许编译器优化volatile指针的dynamic_cast?

时间:2018-09-27 21:38:31

标签: c++ language-lawyer volatile dynamic-cast

看看这个小片段:

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

struct B { };

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

是否允许编译器完全删除dynamic_cast并将dynamic_cast转换为简单的nullptr;

这个问题的原因是这个answer

注意:

  • 假定volatile意味着编译器无法假定关于a的任何信息,因为它是易失的。这是question的原因。

  • 可能不允许删除dynamic_cast的事实是程序中可能存在某个类型,该类型源自AB。 / p>

2 个答案:

答案 0 :(得分:2)

是的,当且仅当编译器可以证明调用的唯一有效结果是{{时,才可以忽略对dynamic_cast的调用。 1}}。很简单。

棘手的部分是证明false的唯一有效结果是dynamic_cast。您可以证明,如果整个程序中没有可以同时继承falseA的类。

现在我对这部分不是很精通,但是我认为,当您创建二进制文件并在程序中具有所有类型时,只有它是可执行文件(而不是库)并且只有在程序没有时,您才能这样做。动态链接到其他库。


1)指针上的B没有副作用,它不会抛出

答案 1 :(得分:2)

是的。 dynamic_cast除了返回值外没有可观察到的行为。

编译器知道a指向的静态类型。

因此,在as-if规则下,编译器可以在编译时自由评估动态转换。

事实上:

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也不破坏一个有任何明显的副作用。

相关问题