anx*_*eux 3 c++ compiler-optimization undefined-behavior
请考虑以下示例:
class Base {
public:
int data_;
};
class Derived : public Base {
public:
void fun() { ::std::cout << "Hi, I'm " << this << ::std::endl; }
};
int main() {
Base base;
Derived *derived = static_cast<Derived*>(&base); // Undefined behavior!
derived->fun();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
根据C++标准,函数调用显然是未定义的行为.但是在所有可用的机器和编译器(VC2005/2008,RH Linux和SunOS上的gcc)上,它按预期工作(打印"嗨!").有谁知道配置此代码可以正常工作?或者可能是具有相同想法的更复杂的例子(注意,Derived不应该携带任何额外的数据)?
更新:
从标准5.2.9/8:
类型"指针CV1 B",其中B是一个类类型的右值,可以转换为类型"指针CV2 d",的右值,其中d是从乙派生的类(第10节),如果一个有效的标准从"指针d"转换到"指针到B"的存在(4.10),CV2是相同cvqualification为或者更大cvqualification比,CV1,和B不是虚拟基类d的空指针值(4.10)转换为目标类型的空指针值.如果类型是"指针CV1 B"点右值进行B实际上是类型d的对象的子对象,将所得指针指向类型D.的包围对象否则,铸造的结果是不确定的.
还有一个9.3.1(感谢@Agent_L):
如果为非X类型的对象或从X派生的类型调用类X的非静态成员函数,则行为未定义.
谢谢,迈克.
该函数fun()实际上并没有做任何与this指针有关的事情,并且由于它不是虚函数,因此查找函数没有什么特别之处.基本上,它被称为任何普通(非成员)函数,具有错误的this指针.它只是不崩溃,这是完全有效的未定义行为(如果这不是一个矛盾).
对代码的注释不正确.
Derived *derived = static_cast<Derived*>(&base);
derived->fun(); // Undefined behavior!
Run Code Online (Sandbox Code Playgroud)
更正版本:
Derived *derived = static_cast<Derived*>(&base); // Undefined behavior!
derived->fun(); // Uses result of undefined behavior
Run Code Online (Sandbox Code Playgroud)
未定义的行为以static_cast.开头.此恶意指针的任何后续使用也是未定义的行为.未定义的行为是为编译器供应商提供的无监狱卡.几乎所有编译器的响应都符合标准.
没有什么可以阻止编译器拒绝你的演员阵容.一个好的编译器可能会发出致命的编译错误static_cast.在这种情况下很容易看到违规行为.一般来说,这并不容易看到,所以大多数编译器都不打扰检查.
大多数编译器都采用最简单的方法.在这种情况下,简单的方法是简单地假装指向类实例的Base指针是指向类实例的指针Derived.由于你的功能Derived::fun()相当温和,在这种情况下简单的出路会产生相当良性的结果.
仅仅因为你获得了良好的良性结果并不意味着一切都很酷.它仍然是未定义的行为.最好的办法是永远不要依赖未定义的行为.