C++中,对象被析构(delete)后,对象仍然可以被使用?求高手帮帮忙!(50分)
初学c++,在学习创建和析构对象时遇到了问题。就是发现已经被delete或是析构的对象,在之后仍然能够使用,比如对象sta已经deletesta后,sta->functi...
初学c++,在学习创建和析构对象时遇到了问题。就是发现已经被delete或是析构的对象,在之后仍然能够使用,比如对象sta 已经delete sta后, sta->function()仍然可以被调用,也就是说sta仍然存在?还是说这段内存其实已经被释放了,不受系统保护,可以被其他的数据刷新,但是由于sta有它的地址,所以可以被调用,但是本人之后把sta设为空指针后,这个对象仍然可以使用!
具体代码如下:(Window 下 visual c++ 6.0)其中注释为遇到的问题
#include<iostream>
using namespace std;
class obj{
public:
obj(){
cout<<"出征啦~~";
}
~obj(){
cout<<"收兵啦";
}
void function();
};
void obj::function(){
cout<<"\nThis is a function!!!";
}
void main(){
//先使用new动态创建一块内存区域
obj *sta=new obj();
//释放掉内存区域后,sta->function()仍然可用!!!
delete sta;
sta->function(); //输出This is a function!!! ???
//现在把sta指针设为0(即NULL),那么还是可以用!!!
sta=0;
sta->function(); //输出This is a function!!! ???
cout<<endl;
//现在直接由其构造函数创建对象
obj sta_2;
//调用析构函数
sta_2.~obj();
//结果还是可以输出function中的内容!!!
sta_2.function(); //输出This is a function!!! ???
//最后原本已经析构完了的对象,系统又析构了一次!!! 输出:收兵啦 ???
}
执行的结果如下:
出征啦~~收兵啦
This is a function!!!
This is a function!!!
出征啦~~收兵啦
This is a function!!!收兵啦press any key to contitue 展开
具体代码如下:(Window 下 visual c++ 6.0)其中注释为遇到的问题
#include<iostream>
using namespace std;
class obj{
public:
obj(){
cout<<"出征啦~~";
}
~obj(){
cout<<"收兵啦";
}
void function();
};
void obj::function(){
cout<<"\nThis is a function!!!";
}
void main(){
//先使用new动态创建一块内存区域
obj *sta=new obj();
//释放掉内存区域后,sta->function()仍然可用!!!
delete sta;
sta->function(); //输出This is a function!!! ???
//现在把sta指针设为0(即NULL),那么还是可以用!!!
sta=0;
sta->function(); //输出This is a function!!! ???
cout<<endl;
//现在直接由其构造函数创建对象
obj sta_2;
//调用析构函数
sta_2.~obj();
//结果还是可以输出function中的内容!!!
sta_2.function(); //输出This is a function!!! ???
//最后原本已经析构完了的对象,系统又析构了一次!!! 输出:收兵啦 ???
}
执行的结果如下:
出征啦~~收兵啦
This is a function!!!
This is a function!!!
出征啦~~收兵啦
This is a function!!!收兵啦press any key to contitue 展开
4个回答
展开全部
你好!!!
首先我们先了解一下类的成员(函数成员和数据成员)内存的分配问题;类的所有的函数成员的是编译时期就已经分配好了内存,我们在定义对象的时候,会调用构造函数(无论是自己定义的还是默认的)此时系统只会给对象的数据成员分配的空间,当对象结束之前的时候,调用析构函数,释放的只是对象的数据成员,对象的函数成员只有在所有程序结束的时候。由此就可以解释你显示调用析构函数后,为什么还可以调用函数成员!!!
关于delete 的用法:它释放的是对象的内存,不知指针变量自己的内存,释放后虽然指针变量还存在,但是此指针所指向的内存已经不存在了,此时的指针就成为”野指针“。但是释放后要是调用对象的成员函数还是可以的,因为成员函数只在程序结束的时候释放,只要此时程序还没有结束就可以使用成员函数。
还你的代码中有显示的调用析构函数:sta_2.~obj();其实析构函数就是普通的函数,用户显式调用析构函数的时候,只是单纯执行析构函数内的语句,不会释放栈内存,摧毁对象。注意析构函数只是释放栈里的内存,堆里的内存必须用free或delete 释放,你写的类中没有数据成员(指针变量还是普通的变量),要是有指针变量的话(要是你在构造函数里为其分配空间),那么你要是显示调用构造函数,就会出现错误,因为对象结束的时候系统还得调用一次析构函数,同一个指针变量释放了两次肯定会出现错误!!!
关于什么时候必须显示调用析构函数,楼主还是先自己找点资料看看看!!!
下面我给你的类添加了一个数据成员x,注意分别在定义对象后和显示调用析构函数输出x,其值是不一样的:
代码如下:
#include<iostream>
using namespace std;
class obj
{
public:
obj()
{x=4;
cout<<"出征啦~~"<<endl;
}
~obj(){
cout<<"收兵啦"<<endl;
}
void function();
int x;//添加一个数据成员
};
void obj::function(){
cout<<"\nThis is a function!!!";
}
void main(){
//先使用new动态创建一块内存区域
obj *sta=new obj();
cout<<"x="<<sta->x<<endl;
//释放掉内存区域后,sta->function()仍然可用!!!
delete sta;
cout<<"x="<<sta->x<<endl;//输入函数成员,输出的就不是4了,因为用delete 释放对象,会系统会调用析构函数释放栈里的资源:如变量x
sta->function(); //输出This is a function!!! ???
//现在把sta指针设为0(即NULL),那么还是可以用!!!
sta=0;
sta->function(); //输出This is a function!!! ???
cout<<endl;
//现在直接由其构造函数创建对象
obj sta_2;
cout<<"x="<<sta_2.x<<endl;//输入函数成员
//调用析构函数
sta_2.~obj();
cout<<"x="<<sta_2.x<<endl;//输入函数成员,输入结果还是4,因为显示调用析构函数不会释放任何内存
//结果还是可以输出function中的内容!!!
sta_2.function(); //输出This is a function!!! ???
}
结果:
出征啦~~
x=4
收兵啦
x=-572662307
This is a function!!!
This is a function!!!
出征啦~~
x=4
收兵啦
x=4
This is a function!!!收兵啦
Press any key to continue
首先我们先了解一下类的成员(函数成员和数据成员)内存的分配问题;类的所有的函数成员的是编译时期就已经分配好了内存,我们在定义对象的时候,会调用构造函数(无论是自己定义的还是默认的)此时系统只会给对象的数据成员分配的空间,当对象结束之前的时候,调用析构函数,释放的只是对象的数据成员,对象的函数成员只有在所有程序结束的时候。由此就可以解释你显示调用析构函数后,为什么还可以调用函数成员!!!
关于delete 的用法:它释放的是对象的内存,不知指针变量自己的内存,释放后虽然指针变量还存在,但是此指针所指向的内存已经不存在了,此时的指针就成为”野指针“。但是释放后要是调用对象的成员函数还是可以的,因为成员函数只在程序结束的时候释放,只要此时程序还没有结束就可以使用成员函数。
还你的代码中有显示的调用析构函数:sta_2.~obj();其实析构函数就是普通的函数,用户显式调用析构函数的时候,只是单纯执行析构函数内的语句,不会释放栈内存,摧毁对象。注意析构函数只是释放栈里的内存,堆里的内存必须用free或delete 释放,你写的类中没有数据成员(指针变量还是普通的变量),要是有指针变量的话(要是你在构造函数里为其分配空间),那么你要是显示调用构造函数,就会出现错误,因为对象结束的时候系统还得调用一次析构函数,同一个指针变量释放了两次肯定会出现错误!!!
关于什么时候必须显示调用析构函数,楼主还是先自己找点资料看看看!!!
下面我给你的类添加了一个数据成员x,注意分别在定义对象后和显示调用析构函数输出x,其值是不一样的:
代码如下:
#include<iostream>
using namespace std;
class obj
{
public:
obj()
{x=4;
cout<<"出征啦~~"<<endl;
}
~obj(){
cout<<"收兵啦"<<endl;
}
void function();
int x;//添加一个数据成员
};
void obj::function(){
cout<<"\nThis is a function!!!";
}
void main(){
//先使用new动态创建一块内存区域
obj *sta=new obj();
cout<<"x="<<sta->x<<endl;
//释放掉内存区域后,sta->function()仍然可用!!!
delete sta;
cout<<"x="<<sta->x<<endl;//输入函数成员,输出的就不是4了,因为用delete 释放对象,会系统会调用析构函数释放栈里的资源:如变量x
sta->function(); //输出This is a function!!! ???
//现在把sta指针设为0(即NULL),那么还是可以用!!!
sta=0;
sta->function(); //输出This is a function!!! ???
cout<<endl;
//现在直接由其构造函数创建对象
obj sta_2;
cout<<"x="<<sta_2.x<<endl;//输入函数成员
//调用析构函数
sta_2.~obj();
cout<<"x="<<sta_2.x<<endl;//输入函数成员,输入结果还是4,因为显示调用析构函数不会释放任何内存
//结果还是可以输出function中的内容!!!
sta_2.function(); //输出This is a function!!! ???
}
结果:
出征啦~~
x=4
收兵啦
x=-572662307
This is a function!!!
This is a function!!!
出征啦~~
x=4
收兵啦
x=4
This is a function!!!收兵啦
Press any key to continue
展开全部
你不明白 析构函数的使用
构函数 不是用来销毁一个类的
而是在一个类销毁的最后时刻自动执行的函数
构函数 不是用来销毁一个类的
而是在一个类销毁的最后时刻自动执行的函数
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
只有数据变量才占用内存空间,函数不会占用内存空间!
我只知道这么多,希望帮的上你.
还有,就是delete虽然在程序中放弃内存空间,可操作系统何时回收空间,我们不太清楚
我只知道这么多,希望帮的上你.
还有,就是delete虽然在程序中放弃内存空间,可操作系统何时回收空间,我们不太清楚
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
1.你使用delete删除对象后并不能真正释放对象,只是原来用new登记到堆上的内存被标记为可以在分配而已。
所以你马上用这个对象的话,大多数情况下(单线程)并不会出错,因为这块内存并没有没有抹掉或者被其他对象覆盖。
2.你自己调用析构函数并不能释放对象,编译器是把析构函数作为一个普通的成员函数来调用的,你如果没有用delete删除或者从函数中返回的话,这个析构函数的真正的内存释放功能并没有得到执行。就算执行过了,就像我上面说的理由,除非你马上把指针置为NULL,这样才能避免这个问题。
另外这个问题很基础,希望你多读书打好基础的东西。
所以你马上用这个对象的话,大多数情况下(单线程)并不会出错,因为这块内存并没有没有抹掉或者被其他对象覆盖。
2.你自己调用析构函数并不能释放对象,编译器是把析构函数作为一个普通的成员函数来调用的,你如果没有用delete删除或者从函数中返回的话,这个析构函数的真正的内存释放功能并没有得到执行。就算执行过了,就像我上面说的理由,除非你马上把指针置为NULL,这样才能避免这个问题。
另外这个问题很基础,希望你多读书打好基础的东西。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询