清楚了一点delete和delete[]

这个帖子,算是解惑了

http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=311058

测试环境用的vs2008……

 1 #include "iostream"
 2 using namespace std;
 3 
 4  class Ttest
 5 {
 6 public:
 7      int objcnt;
 8      int descnt;
 9     Ttest();
10     ~Ttest();
11 };
12  Ttest::Ttest()
13  {
14          static int objcnt=0;
15         cout<<"construct: "<<++objcnt<<endl;
16  }
17  Ttest::~Ttest()
18  {
19      static int descnt=0;
20         cout<<"dest: "<<++descnt<<endl;
21  }
22 void main()
23 {
24     int tempvar;
25     Ttest * p=new Ttest[5];
26     //delete [] p;
27     delete p;
28     cin>>tempvar;
29 
30 
31 }

用delete[]析构整个数组的元素,用delete,析构首元素。

接着往下测试,

 

  发现一个很好玩的现象,若是Ttest * p=new Ttest[5];再delete p;若是在线debug或者生成debug\*.exe文件则代码执行到此则卡住了,若是release\*.exe文件,则可以运行下去。

调试的时候能出现内存错误提示。而且debug和release文件夹下的exe执行结果很不一样,

先贴代码:

 1 #include "iostream"
 2 using namespace std;
 3 
 4 class Ttest
 5 {
 6 public:
 7     int objcnt;
 8     int descnt;
 9     Ttest();
10     ~Ttest();
11 };
12 Ttest::Ttest()
13 {
14     static int objcnt=0;
15     cout<<"construct: "<<++objcnt<<endl;
16 }
17 Ttest::~Ttest()
18 {
19     static int descnt=0;
20     cout<<"dest: "<<++descnt<<endl;
21 }
22 void main()
23 {
24     int tempvar;
25     Ttest * p=new Ttest[5];
26     cout<<"pvaraddr: "<<(long)p<<endl;
27     delete[] p;
28     Ttest * p2=new Ttest[8];
29     cout<<"p2varaddr: "<<(long)p2<<endl;
30     delete[]  p2;
31     Ttest * p3=new Ttest[3];
32     cout<<"p3varaddr: "<<(long)p2<<endl;
33     delete[] p3;
34 //     delete p;
35 //     delete (p+1);
36 
37     char * testcharp=new char[5];
38     cout<<"testcharpaddr: "<<(long)testcharp<<endl;
39     *testcharp='A';
40     *(testcharp+3)='C';
41     delete testcharp;
42 
43     int* testint2=new int;
44     * testint2=0x01010101;
45     cout<<"testint2addr: "<<(long)testint2<<endl;
46     cout<<"testint2 is: "<<hex<<*testint2<<endl;
47     //delete testint2;
48     *(testcharp+2)='C';
49     cout<<"offset 2 is: "<<*(testcharp+2)<<endl;
50     *(testcharp+4)='D';
51     cout<<"offset 4 is: "<<*(testcharp+4)<<endl;
52 
53     *(testcharp+5)='E';
54     cout<<"offset 5 is: "<<*(testcharp+5)<<endl;
55 
56     *(testcharp+800)='L';
57     cout<<"offset 800 is: "<<*(testcharp+800)<<endl;
58 
59     cout<<"testint2 is: "<<hex<<*testint2<<endl;
60 
61     char * testchar2p=new char;
62     *testchar2p='f';
63     cout<<"testchar2paddr: "<<(long)testchar2p<<endl;
64 
65     cin>>tempvar;
66 
67 
68 }

执行结果:

construct: 1
construct: 2
construct: 3
construct: 4
construct: 5
pvaraddr: 3484500
dest: 1
dest: 2
dest: 3
dest: 4
dest: 5
construct: 6
construct: 7
construct: 8
construct: 9
construct: 10
construct: 11
construct: 12
construct: 13
p2varaddr: 3484500
dest: 6
dest: 7
dest: 8
dest: 9
dest: 10
dest: 11
dest: 12
dest: 13
construct: 14
construct: 15
construct: 16
p3varaddr: 3484500
dest: 14
dest: 15
dest: 16
testcharpaddr: 3505088
testint2addr: 3505088
testint2 is: 1010101
offset 2 is: C
offset 4 is: D
offset 5 is: E
offset 800 is: L
testint2 is: 1430101
testchar2paddr: 357bd0

 

结论:

1、debug和release还是有区别的,验证了那句话,对一个事物进行观察时,不可能不对它产生影响,大致如此吧。

2、对于自己生命的对象类型(class),object* pobject=new object[];之后,必须用delete [] pobject;才能调用每个元素的析构函数,并释放所用申请的内存空间。

若是delete pobject;则只调用首元素的析构,并不能释放所有申请的内存空间(貌似只有首次delete才这样,以后delete也是全部释放了,应该是编译器的事吧)

对于基本数据类型时,delete 和delete[] 就没区别了。

3、使用new之后,申请的内存空间之后的一段地址也可以用,这大概是编译器或操作系统做的优化吧。内存这么大,一次给几个字节多麻烦,先给你几百个,需要就自己拿,都用完了再来要,

有点类似于批发吧。还有对于基本类型和自定义对象类型的,new完之后地址也不连续,大概也是一种优化吧。

 

所以还是建议new[]和delete[]配对使用吧。

 

 

posted on 2013-07-15 11:01  zhiying678  阅读(188)  评论(0编辑  收藏  举报

导航