2011年3月

(转)C++为什么不用delete代替delete[]?

总结:一直想不通c++为什么多此一举,呵呵,前几天给Bjarne Stroustrup大师写了一份信,第二天就收到回复了,自己再仔细琢磨了一下,终于好像弄明白了:-)

我的理解是这样的,无论new还是new[ ],C++的确知道返回的这个指针它指向多大的内存块,否则它就不可能正确地释放掉这块内存了。但是delete需要知道的不仅仅是指针指向多大的内存,而更重要的是要知道指针指向的数组中有多少个对象,知道了对象数量才能依次一一调用它们的析构函数。那么,下面的代码会产生什么样的结果??

int * pArray = new int[100];

……

delete pArray; //本来应该是 delete [ ] pArray;

根据上面的解释,我们不难想象,上述代码错误的原因并不是因为它只释放掉第一个元素的空间而没有能完全释放整个pArray所指的内存。 也就是说,在内存释放上不存在问题。问题出在在这里只对第一个元素调用了析构函数,而其他99个元素并没有被妥善地析构掉。呵呵,这才是真正的问题所在!! 当然对于整数类型来说并不会导致什么问题,但假如在每个对象中都分配了额外的资源,那么不调用对象的析构函数可就会导致严重的后果了……

那使用delete[ ]有什么用?这要从new[ ]说起,在new一个数组时,编译器会悄悄地在内存中保存一个整数用来表示数组中元素的个数。这样在使用delete[ ]时,编译器就会生成读取这个整数的代码,然后逐个调用析构函数。如果使用delete,则编译器只当作指针所指的是单个对象。再说了,new单个对象时,编译器也不会悄悄记录数组中元素的个数。呵呵,从这也可以感觉出C++的设计风格和宗旨,决不多费一点手脚,单个对象我就不记录长度,只有是数组时我才记录!:-)

下面是我给Bjarne Stroustrup的邮件及他的回信。在此对Bjarne Stroustrup大师平易近人的风范再次表示钦佩!!

Hi, Dr. Stroustrup

Firstly,Thank you for your great invention, the c++ programming language is
really a great job, it gives me a lot of help in my study, it makes my work much
more convenient!

Thanks

Well, today ,I run into a confused problem about delete and delete[], so I
wonder if you could give me some explanation or tips. I simply can't understand
why c++ don't treat them in the same way. In other words, I think there is no
need for delete[].

For example, "delete [] ps", many textbooks just say that the operator
delete[] is used to tell the compiler that the pointer "ps" refers to an array,
but not a single object. Of course, I know that, but the thing is that I think
the c++ compiler is totally clever enough to figure out whether "ps" points to a
single object or an array. There is no need to bother the programmer to point it
out explicitly.

No. The compiler cannot know.

void f(int* p)
{
delete p; // or maybe delete [] p?
}

void g()
{
int* q = new int[70];
f(q);
q = new int;;
f(q);
}

separately compile those two functions an the compiler had no way of
knowing how many ints p points to.

It's no doubt that the compiler knows the size of storage to which is pointed
by "ps". Otherwise, it's impossible for c++ to deallocate the memory properly.
OK, now that the compiler exactly knows how many bytes is allocated there and
which type the object is, it can compute how many object are there, I mean,
" number of object = number of bytes allocated / sizeof(object type) "
Ok, after that, c++ may call destructor iteratively to destroy each object in
the array and then deallocates the memory.

It is a bit trickier than that. Many allocators allocates space for at
least N ints when you ask for new int[N]. It is not uncommon for an
allocator to allocate more to minimize fragmentation.

I don't know if I have made my question clear:-) In conclusion, I think a
single object is just a special case of an array, so c++ is supposed to deal
with them in the same way. There is no need for us to differentiate delete and
delete[].

The snag is that many allocators (at least traditionally) just keep
track of the number of bytes allocated (rounding the allocation up to
something convenient). With destructors, the compiler has to know how
many objects are there (not just how much space is allocated). Some
implementers use (or used) two different layouts for individual objects
and arrays - the array layout (only) included an object count.

In fact, I know certainly this is my misunderstanding. if not that, the c++
committe should have changed the c++ syntax:-) I just hope to get some
convincing explanation.

Thank you, really appreciate for your help!

Supermonkey,China,Nankai University
2007-09-03