delete的问题

fixopen 2004-08-26 06:26:55
T* o = new T();
void* p = o;
.....

delete p; //what do the delete do?
他能知道p的类型么?怎么能够调用T的析构函数?
...全文
713 63 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
63 条回复
切换为时间正序
请发表友善的回复…
发表回复
fixopen 2004-09-13
  • 打赏
  • 举报
回复
我觉得现在有两个问题需要明确:
1.类型转换时究竟干了什么?他又分成这么几个子问题(我下面的叙述都省略了指针)
a从子类道父类的转换,子类和父类都没有虚函数
b从子类道父类的转换,子类有虚函数,父类没有
c从子类道父类的转换,子类和父类都有虚函数
d没有关系的类间转换,都没有虚函数
e没有关系的类间转换,转换前有的类有虚函数,转换后的类没有虚函数
f没有关系的类间转换,转换前有的类没有虚函数,转换后的类有虚函数
g没有关系的类间转换,都有虚函数
h类转换成原始类型,类没有虚函数
i类转换成原始类型,类有虚函数
j原始类型转换成类,类没有虚函数
k原始类型转换成类,类有虚函数

2.delete xxx究竟干了什么?他又分成这么几个子问题(我下面的叙述都省略了指针)
a.xxx是类类型,且无虚析构
b.xxx是类类型,有虚析构
c.xxx是原始类型
fixopen 2004-09-13
  • 打赏
  • 举报
回复
to ljan(冰魂):

>delete (C*)o;
>若C的析构函数不是虚拟的,那么这样转型,实际告诉编译器把o指针指向的对象按C类型来处理,自然调用C的析构函数,按一般的成员函数来处理。

如果我理解的没错的话,你的意思是说:
T* o = new T();
C* p = (C*)o;

如果delete o,会演化成vptr->vtbl[T's virtual dtor offset],
而如果delete p,会演化成vptr->vtbl[C's virtual dtor offset]
是么?

但如果是这样的话,我认为不可能是在delete xxx的时候确定的,而只能是在类型转换的时候确定的,那就是说,类型转换会导致一定的动作,修改offset值。

to xteaj()
你说的有道理,这也是我前面担心的一个问题
〉哦,我看出可能的问题是什么了,可能的问题是void*的delete会跟free一样,也就是没有析构的调用,因为它毕竟是一个原始类型。
wgsspank 2004-09-13
  • 打赏
  • 举报
回复
我都晕了,呵呵,向高手学习!真是闻道有先后,术业有专攻!
  • 打赏
  • 举报
回复
对于内建类型和类类型,C++在解构时应该是采用两种解构方式的。
对于内建类型,不需要析构过程,直接回收内存就可以了。
如int *p = new int;
delete p;直接回收4Bytes就可以了,不需要更多的处理。
对于类类型,有更多的信息需要处理,所以要比较具体的析构函数。
void是内建类型,采取直接回收内存,但void又是未知类型,无法知道
该释放多少内存,所以就会出问题。
slqit2002 2004-09-12
  • 打赏
  • 举报
回复
我认为c++对不同的指针类型采用了不同的处理方法
riffle 2004-09-12
  • 打赏
  • 举报
回复
用下面的代码似乎更好说明问题:

char *p = new char[ 1 ];

T* o = NULL;
o = ( T* )p;

delete o;

上面的代码拿来执行的话,机器多半会死的。
对于编译器,它只关心delete后面的“东西”是什么(类型),并从而产生相应的代码,而不会
关心那个指针真正指向的是什么。至于说拿基类指针指向子类,然后删除它,能调用正确的析构
函数,那是因为该基类的析构函数是虚函数,将被编译器纳入VTABLE中,所有派生类的析构函数
在VTABLE中的位置都一样,编译器对delete运算符产生的代码都是CALL VTABLE中的对应位置的
那个函数,自然能调用正确的析构函数了。
对于上面的代码,编译器“傻呼呼”地按照T类的析构函数规则去执行,不出问题那就奇怪了。
无论T类的析构造函数是否虚函数,都极可能会出异常。举一个例子,假设T类有一个成员变量
是char *m_p;在其析构函数里有一句delete m_p;想想看,上述代码才为p分配一个字节空
间哪,delete m_p会有什么后果呢?
myling 2004-09-12
  • 打赏
  • 举报
回复
感觉好多人都认为析构函数就是delete一样
jxhwei 2004-09-11
  • 打赏
  • 举报
回复
好搞笑,使用delete跟析构函数有什么关系?!delete单纯的跟new配对使用,你用new得到一段内存空间,那么delete就释放一段内存空间,才不管你new的是什么。
williamVII 2004-09-11
  • 打赏
  • 举报
回复
不能,无法调用析构函数。
ljan 2004-09-11
  • 打赏
  • 举报
回复
这个偏移量就是函数地址在虚函数表中的索引啦,编译时就已经确定好了的
对应T,T',他们的虚拟析构函数,在虚函数表的索引是一样的,只不过在派生类T'的虚函数表中,相同索引位置放的是T' 的析构函数指针而已。

delete (C*)o;
若C的析构函数不是虚拟的,那么这样转型,实际告诉编译器把o指针指向的对象按C类型来处理,自然调用C的析构函数,按一般的成员函数来处理。

若C的析构函数为虚拟函数,假设T的析构函数在虚表中索引为1,那么实际编译器处理为
o->vptr[1],调用的仍为T'的析构函数
Tranum 2004-09-10
  • 打赏
  • 举报
回复
mark
xiao_wang 2004-09-10
  • 打赏
  • 举报
回复
T* o = new T'();
delete (T*)o; //T' dtor

如果这个不出问题的话,有理由认为

T* o = new T'();
delete (C*)o;

会出问题?
当然,我说的都是他们的dtor是虚的。
------------------------------------------------------------------------
我想如果C是T'的父类,那么不会出问题,否则发生错误!
wwwooowww 2004-09-10
  • 打赏
  • 举报
回复
向高手致敬!!!!!
学习!!!!!!!!
fixopen 2004-09-10
  • 打赏
  • 举报
回复
to steedhorse(晨星)
现在的问题的关键是,进行类型转换时,会不会修改其offset值?我觉得好象没有必要。
比如:最常见的父子类转换,应该根本没有必要修改offset值,如果能够向无关的类类进行转换,那么编译器有责任保证还调用到相应的virtual dtor,也就是说,既然它允许,就要保证安全,那么他应该也不会修改offset,你觉得呢?
fixopen 2004-09-10
  • 打赏
  • 举报
回复
to zgy166(昆深)

对void型的指针进行操作之前都应该转型为你想要的类型。
不然是无法正确执行代码的。这是程序员的责任!

呵呵,开个玩笑,我如果要进行free呢?也要类型转换?
fixopen 2004-09-10
  • 打赏
  • 举报
回复
你觉得T'的dtor在vtbl中的偏移量一定跟T相同?
如果C中dtor在vtbl中的偏移量跟T'不同,确实会有问题,但就是说,如果C++编译器允许我做这样的转换,但不保证这样的转换是安全的?他会不会不修改offset?尤其是向void*转换时?那样的话,就会调用到正确的析构了。
zgy166 2004-09-10
  • 打赏
  • 举报
回复
对void型的指针进行操作之前都应该转型为你想要的类型。
不然是无法正确执行代码的。这是程序员的责任!
fixopen 2004-09-10
  • 打赏
  • 举报
回复
也可能sizeof(T') <> sizeof(T)呀。
所以sizeof(C) <> sizeof(T)应该没有关系
yndfcd 2004-09-10
  • 打赏
  • 举报
回复
不能delete一个void类型的指针.
fixopen 2004-09-10
  • 打赏
  • 举报
回复
T* o = new T'();
delete (T*)o; //T' dtor

如果这个不出问题的话,有理由认为

T* o = new T'();
delete (C*)o;

会出问题?
当然,我说的都是他们的dtor是虚的。

哦,我看出可能的问题是什么了,可能的问题是void*的delete会跟free一样,也就是没有析构的调用,因为它毕竟是一个原始类型。
加载更多回复(43)

65,187

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧