一 问题
class B;
int main() {
B* p = nullptr;
delete p;
return 0;
}
编译时,vs2015的警告如下:
警告删除的是一个不完整类型(B只有申明,没有定义),B的析构函数不会调用。在稍大的项目中很容易被忽略。
二 方法
采用一种方式,在编译阶段发现有删除不完整类型之前直接报错。可以借助sizeof,如下
template<typename T>
inline void check_delete(T* t) {
typedef char type_must_be_complete[sizeof(T) ? 1 : -1];
(void) sizeof(type_must_be_complete);
::delete t;
};
原理是针对不完整类型,在不同编译器下sizeof会报错或者返回0,返回0时会定义一个长度为-1的数组,这也是不允许的,所以如果T为不完整类型,编译时会报错,方便检查代码。
三 举例
// A.h
class A {
public:
A();
~A();
};
// A.cpp
#include "A.h"
A::A() {
std::cout << "A()" << std::endl;
}
A::~A() {
std::cout << "~A()" << std::endl;
}
// check_delete.h
template<typename T>
inline void check_delete(T* t) {
typedef char type_must_be_complete[sizeof(T) ? 1 : -1];
(void) sizeof(type_must_be_complete);
::delete t;
};
// B.h
class A;
void func(A* a);
// B.cpp
#include "B.h"
#include "check_delete.h"
void func(A* a) {
check_delete(a);
}
// main.cpp
#include "B.h"
#include "A.h"
int main() {
A* p = new A;
func(p);
std::cin.get();
return 0;
}
编译错误: