C++ 为什么对已删除指针调用非虚拟成员函数是一种未定义的行为?

C++ 为什么对已删除指针调用非虚拟成员函数是一种未定义的行为?,c++,undefined-behavior,language-lawyer,dereference,C++,Undefined Behavior,Language Lawyer,Dereference,如标题所示: 为什么对已删除指针调用非虚拟成员函数是一种未定义的行为? 注意:问题不是问它是否是未定义的行为,而是问它为什么是未定义的行为 以为例: #include<iostream> class Myclass { //int i public: void doSomething() { std::cout<<"Inside doSomething"; //i = 10; }

如标题所示:

为什么对已删除指针调用非虚拟成员函数是一种未定义的行为?

注意:问题不是问它是否是未定义的行为,而是问它为什么是未定义的行为


为例:

#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;
}
#包括
类Myclass
{
//int i
公众:
无效剂量测定法()
{

STD::CUT< P>因为它可能是可靠的,所以它的数量是如此的渺茫,而且它仍然是一个无法实现的愚蠢想法。没有定义行为的好处。

< P>在C++语言中(根据C++ 03)尝试使用无效指针的值已经导致未定义的行为。UB不需要取消引用它。只读取指针值就足够了。“无效值”的概念当您仅尝试读取该值时,这会导致UB实际上扩展到几乎所有标量类型,而不仅仅是指针

delete
之后,指针在特定意义上通常是无效的,即读取假定指向刚刚“删除”的对象的指针会导致未定义的行为

int *p = new int();
delete p;
int *p1 = p; // <- undefined behavior
int*p=newint();
删除p;
int*p1=p;//
那么,为什么标准规定通过deleted指针调用非虚拟成员函数是一种未定义的行为,而事实上它可以可靠地说,取消引用this应该是导致未定义行为的语句

[expr.ref]第2段说,成员函数调用,如
ptr->doSomething()
相当于
(*ptr)。doSomething()
,因此调用非静态成员函数是一种取消引用。如果指针无效,则是未定义的行为

对于特定情况,生成的代码是否确实需要取消引用指针并不相关,编译器建模的抽象机器原则上会进行取消引用

将语言复杂化,以便准确定义只要不访问任何成员就可以允许哪些情况,这几乎没有任何好处。在看不到函数定义的情况下,您不知道调用它是否安全,因为您不知道函数是否使用
this


只是不要这样做,没有很好的理由这样做,而且语言禁止这样做是件好事。

在这种情况下,取消对
this
的引用实际上是一个实现细节。我不是说
this
指针不是由标准定义的,因为它是,但从语义抽象的角度来看,它是什么e允许使用已销毁的对象的目的,仅仅是因为存在一个在实践中是“安全的”的极端情况?没有。所以它不是。没有对象存在,所以你不能对其调用函数。

标准没有强制要求任何东西;这是未定义行为的全部概念。说出你声称的东西就可以了“可靠地说”将是强制性的。编译器永远不能“取消引用”"任何东西。取消引用都是语言结构的一部分。它与代码生成无关。混淆语言和生成的代码是危险的。语言说调用成员函数会计算隐式实例参数,就是这样。如果您想要使用的行为,您应该创建成员函数静态。从道义上讲,只要它不需要任何每个对象的状态,就可以调用when和only,这意味着它应该是静态的。+1.对于没有“this”的静态类成员(上次我检查时仍然是),有充分的理由支持这一点。这在过去为我节省了大量的键入时间。但是对于普通成员(虚拟成员或非虚拟成员)我看不出任何好处。还有+1-如果你有一个非静态成员函数,它对你的对象的状态没有任何作用,为什么它是一个成员函数呢?:Dal虽然乍一看,这样的方法似乎没有理由不是静态的,但我遇到了这样的需要。例如,静态方法s无法实现接口,因此类似于实用程序方法的东西,其实现隐藏在接口后面(或者可能有多个实用程序实现)是纯方法,必须是实例方法才能实现接口。此外,您可能希望实用程序方法是虚拟的,以便它可以被另一个实用程序类重写。静态方法可以实现静态接口。如果接口是非静态的,则需要有效的
this
来查找所需的函数。@jam40jeff,如果函数是虚拟的,那么您需要“取消引用此
”访问vtable,所以它与这个问题无关,特别是说非虚拟。很难不同意这一点。尽管如此,
delete
的想法可能会使指针无效,以至于硬件在看它的时候就会出现故障,这看起来几乎是在飞蜥蜴的级别上。据我所知,没有实现C++中的删除操作符物理地拆解内存芯片,当然标准并不排除这样的实现。但是我不确定我是否希望它在我的办公桌上。不过,C++ 11没有这么说,定义的改变是2012年10月的一个,所以只在最新的WP中,而不是任何标准。ici,DR解释了为什么访问无效指针的值可能会出错。注意:
delete p
的实现将
p
设置为
nullptr
,这是允许的。我对此投了反对票,因为这意味着允许读取无效指针值的实现必须允许calli通过无效指针调用成员函数,该指针不是标准的正确读数。成员函数