这是个老话题了,大家都知道在C++语言中delete一个空指针是安全的。但今天我想讨论的并不是C++标准是否支持delete空指针的操作。且听我慢慢道来...
前几天的检视同事的代码时,发现了一个内存泄露,大体如下:
if(NULL != b.p)
{
a.p = b.p;
b.p = NULL;
}
并且给出了个建议的修改方案:
if(NULL != b.p)
{
if (NULL != a.p)
{
delete []a.p; //这里假定为char*型的
}
a.p = b.p;
b.p = NULL;
}
同事说没必要那么麻烦,不需要判空直接delete就得了,因为C++中delete空指针是安全的,并且他也找到了老代码中有地方确实就是这么写的,我看老代码也这样就没有说什么了,同意了他的修改方法。 今天回家时又在想这个问题,到底要不要判空,这两者那个更可取!表面上看不判空直接delete的方法确实方便,直观。但当我想到delete\delete[]操作实际是函数调用时,顿然想到了效率问题;先看不判空直接delete汇编代码:
if (NULL != b.p)
003E1400 cmp dword ptr [b],0
003E1404 je main+7Bh (3E142Bh)
{
delete []a.p;
003E1406 mov eax,dword ptr [a]
003E1409 mov dword ptr [ebp-0E0h],eax
003E140F mov ecx,dword ptr [ebp-0E0h]
003E1415 push ecx
003E1416 call operator delete[] (3E11D6h)
003E141B add esp,4
a.p = b.p;
003E141E mov eax,dword ptr [b]
003E1421 mov dword ptr [a],eax
b.p = NULL;
003E1424 mov dword ptr [b],0
}
如上,delete []a.p;被汇编成5条指令+一次函数调用;这样,即使指针为空也会执行如上指令,与非空的情况唯一的差别就是delete函数中少做了些事而已。而如果先进行一次判空的话,当指针会空时会少走很多弯路。请看:
if (NULL != b.p)
00143600 cmp dword ptr [b],0
00143604 je main+88h (143638h)
{
if (NULL != a.p)
00143606 cmp dword ptr [a],0
0014360A je main+7Bh (14362Bh)
{
delete []a.p;
0014360C mov eax,dword ptr [a]
0014360F mov dword ptr [ebp-0E0h],eax
00143615 mov ecx,dword ptr [ebp-0E0h]
0014361B push ecx
0014361C call operator delete[] (1411D6h)
00143621 add esp,4
a.p =NULL;
00143624 mov dword ptr [a],0
}
a.p = b.p;
0014362B mov eax,dword ptr [b]
0014362E mov dword ptr [a],eax
b.p = NULL;
00143631 mov dword ptr [b],0
}
如上、跳过了delete函数调用和其他些指令,这样效率自然高了。对于指针为空的情况,第二中方案也仅比不判空多了一条条件跳转语句“0014360A je main+7Bh (14362Bh) ”而已,效率不会差多少。
说了一大堆,其实是个很简单的道理,明白者就当温习下,见笑了!