在对象被显式销毁之后但在内存被释放之前调用成员函数是否合法? [英] Is it legal to call member functions after an object has been explicitly destroyed but before its memory was deallocated?

查看:394
本文介绍了在对象被显式销毁之后但在内存被释放之前调用成员函数是否合法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码:

  struct data {
void doNothing(){}
} ;

int main(){
data * ptr = new data();
ptr->〜data();
ptr-> doNothing();
:: operator delete(ptr);
}

注意 doNothing()在对象被销毁之后但在其内存被释放之前被调用。它看起来像对象生命周期已经结束,但指针仍指向正确分配的内存。成员函数不访问任何成员变量。



成员函数调用在这种情况下是合法的吗?

解决方案

是的,在OP的代码的情况下。因为析构函数是微不足道的,调用它不会结束对象的生命周期。 [basic.life] / p1:


类型 T 结束于:




  • 如果 T 析构函数(12.4),析构函数调用开始,或

  • 对象占用的存储被重用或释放。


[class.dtor] / p5:


一个析构函数不是用户提供的,如果:




  • 析构函数不是 virtual / li>
  • 其类的所有直接基类都具有简单的析构函数,并且

  • 为其类的所有非静态数据成员类类型(或其数组),每个类都有一个无关紧要的
    析构函数。


不,在一般情况下。在对象的生命周期结束后调用非静态成员函数是UB。对象的生命周期已经结束,在存储之前,
[A] [p]:[basic.life] / p5:



<被占用的对象被重用或释放,引用
的任何指针将是或将被定位在该对象的存储位置可以是
,但仅以有限的方式使用。对于正在建造或销毁的对象,请参见12.7。否则,这样的指针指向分配的
存储(3.7.4.2),并且使用指针,如同指针是
类型 void * 是明确定义的。通过这种指针的间接是允许的
,但是结果的左值只能以有限的方式使用
,如下所述。该程序未定义
行为如果:




  • [...]

  • 指针用于访问非静态数据成员或调用对象的非静态成员函数,或

  • [...]



    • I have this code:

      struct data {
        void doNothing() {}
      };
      
      int main() {
          data* ptr = new data();
          ptr->~data();
          ptr->doNothing();
          ::operator delete(ptr);
      }
      

      Note that doNothing() is being called after the object has been destroyed but before its memory was deallocated. It looks like "object lifetime" has ended however the pointer still points to proper allocated memory. The member function does not access any member variables.

      Would member function call be legal in this case?

      解决方案

      Yes, in the case of the code in the OP. Because the destructor is trivial, calling it doesn't end the object's lifetime. [basic.life]/p1:

      The lifetime of an object of type T ends when:

      • if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
      • the storage which the object occupies is reused or released.

      [class.dtor]/p5:

      A destructor is trivial if it is not user-provided and if:

      • the destructor is not virtual,
      • all of the direct base classes of its class have trivial destructors, and
      • for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor.

      No, not in the general case. Invoking a non-static member function after the object's lifetime has ended is UB. [basic.life]/p5:

      [A]fter the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a pointer refers to allocated storage (3.7.4.2), and using the pointer as if the pointer were of type void*, is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below. The program has undefined behavior if:

      • [...]
      • the pointer is used to access a non-static data member or call a non-static member function of the object, or
      • [...]

      这篇关于在对象被显式销毁之后但在内存被释放之前调用成员函数是否合法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆