参数进行检测是一直都推荐的。例如、如果你设计的函数是公共API的一部分,它可能被外部客户端调用,这样很难保证客户端传进入的参数就是正确的。
例如,让我们来看看这个hypotethical DrawVehicle()?函数,它可以根据不同的质量来绘制一辆跑车,这个质量数值(nDrawingQaulity )是0~100。prcDraw?定义这辆跑车的轮廓区域。
看看下面代码,注意观察我们是如何在使用函数参数之前进行参数检测:
BOOL DrawVehicle(HWND hWnd, LPRECT prcDraw, int nDrawingQuality)
{
// Check that window is valid
if(!IsWindow(hWnd))
return FALSE;
// Check that drawing rect is valid
if(prcDraw==NULL)
return FALSE;
// Check drawing quality is valid
if(nDrawingQuality<0 || nDrawingQuality>100)
return FALSE;
// Now it's safe to draw the vehicle
// ...
return TRUE;
}
在指针使用之前,不检测是非常普遍的,这个可以说是我们引起软件崩溃最有可能的原因。如果你用一个指针,这个指针刚好是NULL,那么你的程序在运行时,将报出异常。
CVehicle* pVehicle = GetCurrentVehicle();
// Validate pointer
if(pVehicle==NULL)
{
// Invalid pointer, do not use it!
return FALSE;
}
// Use the pointer
Initializing Function Output
如果你的函数创建了一个对象,并要将它作为函数的返回参数。那么记得在使用之前把他复制为NULL。如不然,这个函数的调用者将使用这个无效的指针,进而一起程序错误。如下错误代码:
int CreateVehicle(CVehicle** ppVehicle)
{
if(CanCreateVehicle())
{
*ppVehicle = new CVehicle();
return 1;
}
// If CanCreateVehicle() returns FALSE,
// the pointer to *ppVehcile would never be set!
return 0;
}
正确的代码如下;
int CreateVehicle(CVehicle** ppVehicle)
{
// First initialize the output parameter with NULL
*ppVehicle = NULL;
if(CanCreateVehicle())
{
*ppVehicle = new CVehicle();
return 1;
}
return 0;
}
Cleaning Up Pointers to Deleted Objects
在内存释放之后,无比将指针复制为NULL。这样可以确保程序的没有那个地方会再使用无效指针。其实就是,访问一个已经被删除的对象地址,将引起程序异常。如下代码展示如何清除一个指针指向的对象:
// Create object
CVehicle* pVehicle = new CVehicle();
delete pVehicle; // Free pointer
pVehicle = NULL; // Set pointer with NULL
Cleaning Up Released Handles
在释放一个句柄之前,务必将这个句柄复制伪NULL (0或则其他默认值)。这样能够保证程序其他地方不会重复使用无效句柄。看看如下代码,如何清除一个Windows API的文件句柄:
HANDLE hFile = INVALID_HANDLE_VALUE;
// Open file
hFile = CreateFile(_T("example.dat"), FILE_READ|FILE_WRITE, FILE_OPEN_EXISTING);
if(hFile==INVALID_HANDLE_VALUE)
{
return FALSE; // Error opening file
}
// Do something with file
// Finally, close the handle
if(hFile!=INVALID_HANDLE_VALUE)
{
CloseHandle(hFile); // Close handle to file
hFile = INVALID_HANDLE_VALUE; // Clean up handle
}
下面代码展示如何清除File *句柄:
// First init file handle pointer with NULL
FILE* f = NULL;
// Open handle to file
errno_t err = _tfopen_s(_T("example.dat"), _T("rb"));
if(err!=0 || f==NULL)
return FALSE; // Error opening file
// Do something with file
// When finished, close the handle
if(f!=NULL) // Check that handle is valid
{
fclose(f);
f = NULL; // Clean up pointer to handle
}
Using delete [] Operator for Arrays
如果你分配一个单独的对象,可以直接使用new?,同样你释放单个对象的时候,可以直接使用delete . 然而,申请一个对象数组对象的时候可以使用new,但是释放的时候就不能使用delete ,而必须使用delete[]:
// Create an array of objects
CVehicle* paVehicles = new CVehicle[10];
delete [] paVehicles; // Free pointer to array
paVehicles = NULL; // Set pointer with NULL
或者:
// Create a buffer of bytes
LPBYTE pBuffer = new BYTE[255];
delete [] pBuffer; // Free pointer to array
pBuffer = NULL; // Set pointer with NULL
Allocating Mem