C++ 如果删除正在运行的方法的对象,该方法会发生什么情况?

C++ 如果删除正在运行的方法的对象,该方法会发生什么情况?,c++,oop,c++11,C++,Oop,C++11,我是StackOverflow的新手,我的第一个问题是,当我删除一个正在运行的方法的对象时,它会发生什么?此外,删除旧对象后,在方法中创建新对象时会发生什么情况 下面有一个小代码片段来澄清我的问题。(用C++11编程) 如果现在调用方法doSomething(): 该方法会一直运行到结束还是会被中断 如果它一直运行到结束,它是属于已删除的对象还是新对象?已删除的对象和新对象都具有相同的名称 如果它被打断,会发生什么?还是这种行为没有定义 到目前为止,我已经过期了,似乎该方法将运行到它的末尾,并在

我是StackOverflow的新手,我的第一个问题是,当我删除一个正在运行的方法的对象时,它会发生什么?此外,删除旧对象后,在方法中创建新对象时会发生什么情况

下面有一个小代码片段来澄清我的问题。(用C++11编程)

如果现在调用方法
doSomething()

  • 该方法会一直运行到结束还是会被中断
  • 如果它一直运行到结束,它是属于已删除的
    对象还是新对象?已删除的对象和新对象都具有相同的名称
  • 如果它被打断,会发生什么?还是这种行为没有定义
  • 到目前为止,我已经过期了,似乎该方法将运行到它的末尾,并在途中执行所有命令,只要它们不影响已删除的对象。例如,允许操作静态变量,如
    counterFromClass
    。而且,似乎还可以在方法内部操作对象的数据成员,如
    counterFromObject
    ,只要在delete命令之前对它们进行操作即可

    好吧,代码可以工作,但我知道这不是最好的编程风格。所以我开始研究一个更好的解决方案,但我仍然好奇到底发生了什么,我的想法是否正确。如能得到答复,我将不胜感激

    如果问题有问题,请告诉我,因为我还不太熟悉在StackOverflow上提问。

    谢谢:)

    删除对象会使此指针无效。创建一个新对象可能(但不是100%)会给您一个新指针。但在上面的代码中,此指针不会神奇地更改为新对象。你有未定义的行为

    对象的代码和分配的空间分别存储。代码只在二进制文件中存储一次(并在执行二进制文件时加载到内存中)。对象在内存中、堆上或堆栈上动态创建。方法的代码使用
    this
    指针(它是方法的“不可见”参数,可以通过在方法中显式写入
    this
    来访问,或者在访问成员时隐式使用)对对象的数据进行操作

    如果删除对象,运行的函数将不会发生任何变化。它将继续运行并执行命令。
    指针在执行过程中不会更改(因为,正如前面提到的,它类似于按值复制的函数的参数)。但是,如果删除该对象,它很可能不会指向任何有用的内容。因此:

    • 使用
      指针会给您一个SEGFAULT,因为您访问的内存不再属于应用程序
    • 或者将访问应用程序中的一些随机内存,导致未定义的行为
    因此,要回答您的问题:

  • 不,没有中断。它继续执行该函数
  • 它不“属于”任何东西,只对
    this
    指向的数据进行操作。您的第二个新指针不能保证为您提供相同的指针值(内存地址)
  • 它不会被中断,但如果您继续访问对象成员,则会导致未定义的行为

  • 从技术上讲,这是未定义的行为。然而,实际上,大多数编译器实现将方法指令存储在内存中的相同位置,而不管这些方法是否是静态的,就像类的静态成员变量存储在内存中的相同位置一样。这是因为方法逻辑不会因实例而异。每个实例存储在不同内存中的是非静态成员变量

    此外,在编译时,会向函数中添加一个隐式参数,该参数是指向类实例的指针。这就是编译函数通过隐式“this”指针访问成员变量的方式


    因此,当您在执行函数的中间删除对象时,它将继续执行,直到它尝试使用非静态成员变量,该非静态成员变量存储在为该对象分配的内存中,该对象现在已被解除分配。此时,如果内存尚未回收,或者如果幸运的话,程序将崩溃,它可能会继续执行。

    让我们一步一步地执行此功能:

    void MyClass::doSomething() {
        this->counterFromObject++;
    
    这是完全合法的。但你知道的

        delete object;
    
    同样,完全合法。但是,在此之后,您的工作是确保不再有代码试图访问
    对象
    指针后面的对象。问题是,当前运行的方法的
    这个
    指针包含死对象地址的副本;
    指针悬空。因此,以任何方式(显式或隐式)取消对该
    的引用都将立即产生未定义的行为

        MyClass* object = new MyClass();    //I added the missing * to the type, we are not using java here.
    
    这不会取消对该
    的引用,因此完全可以。请注意,这对当前正在运行的方法没有任何影响。
    指针悬空,无法重新分配

        this->counterFromClass++;
    
    从形式上讲,这是未定义的行为,因为您正在取消对该
    的引用。但是,由于
    counterFromClass
    是静态的,这很可能不会使进程崩溃,因为编译后的代码实际上不会访问
    this
    后面的内存。尽管如此,编写
    this->
    意味着您有未定义的行为,因此您的进程可能会崩溃,或者您的编译器可能会直接丢弃此语句!它是否这样做只取决于编译器是否足够聪明,能够证明您在这里有未定义的行为。
    (正如MartinBonner所发现的,该标准在第9.4节中指出,即使通过
    this->
    访问静态成员,也会对对象表达式进行评估,这意味着悬空
    
    
        this->counterFromClass++;