void* 类型指针能否使用 delete 释放空间?
答案是取决于指向的对象:
// 只包含基本类型
typedef struct A {
char name[32];
int age;
double score;
} A;
// 包含指针和对象
typedef struct B {
char *name;
int age;
double score;
std::string addr;
} B;
// 与 B 一样包含对象
typedef struct C {
char name[32];
int age;
double score;
std::vector<int> arr;
} C;
// 包含 A 对象
typedef struct D {
char name[32];
int x;
int y;
A a;
} D;
int main()
{
void* vptr;
A* a = new A();
void* vptr = a;
delete vptr; // 没问题, 类型A的大小固定, 且无指针
B* b = new B();
b->addr = std::string(50000000, '=');
vptr = b;
delete vptr; // 泄漏。name 指向的外部空间未释放; std::string 空间未释放
C* c = new C();
c->arr = std::vector<int>(50000000);
vptr = c;
delete vptr; // 泄漏. std::vector 空间未释放. std::vector 数据始终保存在堆上, 需要调用析构;
D* d = new D();
vptr = d;
delete vptr; // 没问题.A 不是指针,且 A 内不存在 "外部" 空间
}
对于每一块已分配的内存,操作系统是知道它的范围的(通过在分配范围的前后加标记),也就是说,你申请一块内存空间,分配的实际大小比你申请的略大。所以不需要知道类型,用 void* 也能释放这块内存。
总结来说:
- 没有指向 “外部” 空间的,如 基本类型,可以用 void* 释放;
- 指向外部空间的,即使不是指针,如 std::string,std::vector 容器,它们的元素不是保存在所在类型(B,C)内,而是在 “外部” 空间,会造成内存泄漏;