Chinaunix首页 | 论坛 | 博客
  • 博客访问: 994173
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-11-11 10:33:34


个人认为delete this:

1. 将对象的删除放到了一个成员函数里,所以就应该屏蔽用户在函数外直接调用其析构函数了,因此应该将析构函数私有化或者protect化。

2. 既然只允许delete对象,那么该对象一定是建立在heap上的,因此应禁止用户在函数外直接调用构造函数在stack上,因此构造函数也应private。

3. 在删除的是一个类的数据部分,而其代码部分和数据部分是不在一起的。因此调用了delete this后,其类的各个函数的代码还是存在的。但是对象数据部分应该被释放了。

摘自:csdn

delete this?

kaku_you(正义的味方)2002-09-11 12:35:55 在 C/C++ / C语言 提问

今天看到网上大拿写的一个很有意思的写法,在一个类成员里有delete   this  
  例如如下例子类  
  class   VSCLS  
  {  
  public:  
  void   stop()  
  {  
  delete   this;  
  return;  
  };  
  ~VSCLS()  
  {  
  printf("ENDING...\n");  
  };  
  };  
   
  如果我既调stop又delete,就会打印两遍ENDING...  
  这样写法安全吗?是用来防止内存泄漏吗?或者根本就是不对的 问题点数:50、回复次数:28

oyxiaoyu0(小雨仔)回复于 2002-09-11 12:39:03 得分 0

目的是调用STOP就会自动释放当前对象!  
   
  如果既调stop又delete,当然就会打印两遍ENDING...  
  不过他的目的是只调STOP。

stonespace(stonespace)回复于 2002-09-11 12:40:44 得分 0

这样写很不安全,但是严格遵循额外的规则,可以保持正确:  
   
  所有实例必须用new生成,不能用delete删除,只能用stop来删除,stop之后必须把指针置为NULL。  
   
  如果stop后delete会导致内存访问错误。绝对不行。

sandrowjw(我的小猫照片给弄坏了,心都碎了)回复于 2002-09-11 12:54:05 得分 0

楼上所言。

julyclyde(Java初学(大学不教只好自己学))回复于 2002-09-11 13:01:16 得分 0

调用了stop以后,还能delete它?真是奇怪啊

cwanter(亚玛逊河上的渔夫)回复于 2002-09-11 13:08:54 得分 0

有必要吗?

coppermine(coppermine)回复于 2002-09-11 13:15:00 得分 0

调用stop后在delete在不同的编译系统中可能会有不同的表现,非常危险.因为stop之后对象已经自杀,再调用delete去删除不存在的对象,显然是错误的.  
   
  一般来说,这样的对象是堆中的对象,stop栈内的对象就会出问题.要禁止对象被分配在栈中,类的构造函数将被设为private,同时添加一个public函数,如   Type   *Create(){   new   Type;}

sizhi(人在江湖飘啊~,哪能不挨刀啊~~)回复于 2002-09-11 14:02:10 得分 0

关注!

crazy_c()回复于 2002-09-11 14:32:42 得分 0

Too   simple,   sometimes   naive.  
   
  The   destructure   should   be   private,   so   that   the   object   must   be   performed   by   new,   and   you   must   destroy   it   by   stop   instead   of   delete.

spanzhang(红尘斩丝客)回复于 2002-09-11 15:03:52 得分 0

英语这么烂!

kenryHuang(冷的时候我想死)回复于 2002-09-11 15:24:23 得分 0

至于你打印两遍..那是stop()   中的delete   this引发了dtor  
   
  然后你又delete对象的话,意思是对一个指针调用两次delete.  
  这样的行为用标准C++来说,就是未定义。  
   
  未定义的后果就是一般时候或许都好好的。。但某个关键时候它爆发了。  
 

ice1010(Azrael)回复于 2002-09-11 15:42:41 得分 0

这个程序在STOP中DELETE了自己,但是如果不是用NEW来产生的对象,  
  为什么还要用DELETE来删除呢(在很多经典的书中都说,NEW要与DELETE  
  配对使用).如果是用NEW来产生的对象,那么在外部DELETE和调用STOP()  
  有什么区别呢?这样做不是很好吧,而且很容易产生上面有人说的那种错误.  
  也许我还是个菜鸟,没有理解其中有什么奥妙.关注高手来解答.

Solstice(大佛)回复于 2002-09-11 16:11:37 得分 0

More   Effective   C++上,  
  有一个条款,教你把dtor做成private(这样就只能用new来产生object,不能用作local   object)。要销毁这样的对象,需要有一个类似上面stop()的member   function,其中就有delete   this;这句。

sandrowjw(我的小猫照片给弄坏了,心都碎了)回复于 2002-09-11 19:47:30 得分 0

实际上stop也应该是被隐藏的,暴露的应该只是对象的一系列行为规则,在对象失去作用后,有判断的机制自动调用stop,这样就形成对象的自动生命周期,完全透明的。

fqcd555(love violet)回复于 2002-09-11 22:59:34 得分 0

study!

julyclyde(Java初学(大学不教只好自己学))回复于 2002-09-13 23:44:18 得分 0

两次删除其实是不一样的。以下程序可以证明:  
  #include    
  class   VSCLS  
  {  
  public:  
  VSCLS(){i=9;}  
  void   stop()  
  {  
  delete   this;  
  return;  
  };  
  ~VSCLS()  
  {  
  std::printf("ending%d",i);  
  };  
  private:  
  int   i;  
  };  
   
  main(){  
  VSCLS*   a=new   VSCLS;  
  a->stop();  
  delete   a;  
   
  }

julyclyde(Java初学(大学不教只好自己学))回复于 2002-09-13 23:44:26 得分 0

看来这次我拿到分了

julyclyde(Java初学(大学不教只好自己学))回复于 2002-09-14 13:09:46 得分 0

cow!好没气氛啊,怎么都不说话啦?

impeng(鹏)回复于 2002-09-14 13:29:50 得分 0

this和a好像都是指向的同一地址,该地址在heap中,保存的是new生成的对象!  
   
  如果是这样,那么,调用a->stop后,由delete删除了该块内存,其结果是造成a指向的区域未有定义(已经删除了,释放回堆中,随时可供其它new使用)!  
   
  这样,如果在接下来的代码中调用delete   a,则是删除了不明区域,其结果同样未有定义!  
   
  在c++中删除一个null的指针是安全的,但c++同样不允许我们修改this的值!  
   
  所以,这样做,个人认为是很不安全的!

liangshulsh(天狼)回复于 2002-09-14 13:59:23 得分 0

up

julyclyde(Java初学(大学不教只好自己学))回复于 2002-09-14 22:22:05 得分 0

错啦  
  第一次仅仅删除了member   data而已。而function还是存在地  
  我上面那段程序用BCC和GCC都编译通过的。  
  我说的不是标准,而是事实。虽然编译器没有按照标准去做,但是我们要承认事实

dhy311(好好学习,天天向上)回复于 2002-09-14 22:39:36 得分 0

/*这是非常危险的,因为在你调用了一次方法stop以后,对象指针相当于已经没有初始化  
  下面的程序是能够编译通过,但是程序在调用第二次的stop时候,由于stop函数不是static,就是没有实例化的对象是没有权利调用非static成员函数的,  
  所以程序出错了*/  
  #include    
  #include    
  class   VSCLS  
  {  
  public:  
  void   stop()  
  {  
  delete   this;  
  return;  
  };  
  ~VSCLS()  
  {  
  printf("ENDING...\n");  
  };  
  };  
  void   main()  
  {  
  VSCLS   *p=new   VSCLS();  
  int   i=0;  
  for(   i   =   0;   i<2;i++)  
  {  
  i++;  
  p->stop();  
  cout<<"it's   ok   when   i   =   "<      
  }  
  delete   p;  
  }  
 

dhy311(好好学习,天天向上)回复于 2002-09-14 22:42:00 得分 0

程序有个地方写错了  
  #include    
  #include    
  class   VSCLS  
  {  
  public:  
  void   stop()  
  {  
  delete   this;  
  return;  
  };  
  ~VSCLS()  
  {  
  printf("ENDING...\n");  
  };  
  };  
  void   main()  
  {  
  VSCLS   *p=new   VSCLS();  
  int   i=0;  
  for(   i   =   0;   i<2;i++)  
  {  
   
  p->stop();  
  cout<<"it's   ok   when   i   =   "<      
  }  
  delete   p;  
  }  
   
 

impeng(鹏)回复于 2002-09-14 22:57:48 得分 0

编译是可以通过的,不过运行时就有问题啦!  
   
  毕竟这里试图删除一块包含未知区域的内存区,而编译器当然不会负责check这件事情!

impeng(鹏)回复于 2002-09-15 13:00:48 得分 0

试着把delete   a   和   a->stop换个位置,效果几乎是相同的!

julyclyde(Java初学(大学不教只好自己学))回复于 2002-09-15 13:47:16 得分 0

本来两次就都是delete嘛

Tommy()回复于 2002-09-15 15:31:23 得分 10

这种写法是有特殊用途的,肯定还有一些其它措施以保证它的正确使用。比如楼上说的用private的构造函数防止用户直接delete,用其它方法保证对象一定在堆上创建等等,只有这样才能保证这个类不被误用。  
   
  to     julyclyde(从ASP转向CPP,到处都是P)   :  
  第一次仅仅删除了member   data而已。而function还是存在地  
  我上面那段程序用BCC和GCC都编译通过的。  
  我说的不是标准,而是事实。虽然编译器没有按照标准去做,但是我们要承认事实  
  ===================  
  这不是什么标准不标准的事,删除两次绝对是错误的,但是,在编译阶段发现不了这个问题,编译器怎么知道在a.stop()后,a对象就已经释放了呢?所以编译肯定可以通过的。  
  删除了对象,不等于对象原来占用的空间就会清除,对象原来的空间上还是会保留原来的内容,直到再次分配出去,在其它地方被修改,所以释放了的对象在很多时候操作起来好像还是正确的。

andy_show()回复于 2002-09-15 15:48:34 得分 20

这样的写法在某些地方有特殊用途,比如我需要实现一个基于引用计数的智能指针,那么我会要求对象在计数达到0的时候用delete   this删除自身。这种用法的实例在许多地方都可以见到。比如VC中的_com_ptr_t以及CORBA中的var类型。  
   
   
   
 

impeng(鹏)回复于 2002-09-15 20:31:52 得分 20

“delete   this”的另一个用途就是用在线程的消亡上。  
   
  当线程由于某种原因,不能(不想)通过正常的顺序结束时,会选择“自杀”的方式结束,释放一些资源(不是全部)!“delete   this”可以帮它做到这一点。  
   
  今天在书上看到这一内容,顺便拿来贴在这里!  
 

以下摘自:http://www.cppblog.com/lovedday/archive/2008/06/03/52060.html

In order to understand "delete this" :

First Step------dive into "delete p"

delete p 执行了哪两个步骤?
delete p 是一个两步的过程:调用析构函数,然后释放内存。delete p产生的代码看上去是这样的(假设是Fred*类型的):

// 原始码:delete p;
if (p != NULL)
{
   p->~Fred();
   operator delete(p);
}

p->~Fred() 语句调用 p 指向的Fred 对象的析构函数。

operator delete(p) 语句调用内存释放原语 void operator delete(void* p)。

Second Step-------"delete this"

成员函数调用delete this合法吗?
只要你小心,一个对象请求自杀(delete this),是可以的。

以下是我对“小心”的定义:

你必须100%的确定,this对象是用 new分配的(不是用new[],也不是用定位放置 new,也不是一个栈上的局部对象,也不是全局的,也不是另一个对象的成员,而是明白的普通的new)。

你必须100%的确定,该成员函数是this对象最后调用的的成员函数。

你必须100%的确定,剩下的成员函数(delete this之后的)不接触到 this对象任何一块(包括调用任何其他成员函数或访问任何数据成员)。

你必须 100%的确定,在delete this之后不再去访问this指针。换句话说,你不能去检查它,将它和其他指针比较,和 NULL比较,打印它,转换它,对它做任何事。

自然,对于这种情况还要习惯性地告诫:当你的指针是一个指向基类类型的指针,而没有虚析构函数时(也不可以 delete this)。

注意:因为是在类成员函数里面delete this的,所以在此语句以后,不能访问任何的成员变量及虚函数,否则一定非法。


阅读(2408) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~