c – 为什么在删除指针上调用非虚拟成员函数是不确定的行为?
正如标题所说:
为什么在删除指针上调用非虚拟成员函数是未定义的行为? 注意问题不会询问它是否是未定义的行为,它会询问为什么它是未定义的行为. 考虑following program: #include<iostream> class Myclass { //int i public: void doSomething() { std::cout<<"Inside doSomething"; //i = 10; } }; int main() { Myclass *ptr = new Myclass; delete ptr; ptr->doSomething(); return 0; } 在上面的代码中,编译器在调用成员函数doSomething()时实际上并没有取消引用它.请注意,该功能不是虚拟功能&编译器将成员函数调用转换为通常的函数调用,将其作为第一个参数传递给函数(据我所知,这是实现定义的).他们可以这样做,因为编译器可以准确地确定在编译时调用哪个函数.所以实际上,通过删除指针调用成员函数不会取消引用它.只有在函数体内部访问任何成员时,才会取消引用它.(即:在上面的示例中取消注释访问i的代码) 那么为什么通过删除指针调用非虚拟成员函数的标准命令是一个未定义的行为,实际上它可以可靠地说解除引用它应该是应该导致未定义行为的语句?仅仅为了语言用户的简单起见,标准只是概括它还是在这个任务中涉及更深层次的语义? 我的感觉是,也许因为它是实现定义编译器如何调用成员函数可能是标准不能强制执行UB的实际点的原因. 有人可以证实吗? 解决方法
[expr.ref]第2段说成员函数调用如ptr-> doSomething()等同于(* ptr).doSomething()所以调用非静态成员函数是一个解除引用.如果指针无效则表示未定义的行为. 生成的代码是否实际需要取消引用特定情况的指针是不相关的,编译器模型的抽象机器原则上会进行解除引用. 使语言复杂化以准确定义哪些情况将被允许,只要它们不访问任何成员就几乎没有任何好处.在您无法看到函数定义的情况下,您不知道调用它是否安全,因为您无法知道函数是否使用此函数. 只是不要这样做,没有充分的理由,语言禁止它是一件好事. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |