void* 是 C++ 中唯一能接收任意对象地址但不可直接解引用的指针类型,因缺乏类型信息而需强制转换为具体类型后才能访问;常用于 malloc/free、qsort 等泛型场景,但易引发未定义行为。

void\* 是什么,为什么不能直接解引用
void* 是 C++ 中唯一能接收任意对象地址的指针类型,但它不携带类型信息。编译器禁止对 void* 直接使用 * 或 ->,因为不知道该读几个字节、怎么解释那块内存。
常见错误现象:
void* p = &x; int y = *p; // 错误:invalid use of 'void*' in arithmetic or indirection
必须先强制转回具体类型指针才能访问:
- 用
static_cast(推荐):类型安全,编译期检查 - 用 C 风格
(int*)p或reinterpret_cast:绕过类型检查,容易出错
malloc/free 场景下 void\* 的典型用法
C 标准库函数 malloc 返回 void*,C++ 中虽可隐式转为任意指针,但显式转换更清晰、兼容性更好(尤其跨平台或混用 C 头文件时)。
立即学习“C++免费学习笔记(深入)”;
int* arr = static_cast(malloc(10 * sizeof(int))); if (arr != nullptr) { arr[0] = 42; free(arr); // 注意:free 只接受 void* }
关键点:
-
free参数是void*,传int*没问题(自动转) -
new/delete不涉及void*,它们自带类型信息,优先用new int[10]而非malloc - 别对
new出来的地址调用free,或对malloc出来的地址调用delete
函数参数中 void\* 用于泛型接口(如 qsort)
C 风格回调函数常靠 void* 实现“伪泛型”,例如 qsort 的比较函数签名是:int (*)(const void*, const void*)。
写比较函数时必须手动转回原类型:
int compare_ints(const void* a, const void* b) {
int ia = *static_cast(a); // 注意 const 修饰要匹配
int ib = *static_cast(b);
return (ia > ib) - (ia < ib);
}
// 使用:
int data[] = {3, 1, 4};
qsort(data, 3, sizeof(int), compare_ints); 容易踩的坑:
- 忘记加
const导致编译失败(qsort传入的是const void*) - 结构体比较时,只转指针不转成员访问方式,比如
static_cast(a)->field - C++ 中更推荐用
std::sort+ lambda,避免void*手动转换
void\* 和 reinterpret_cast 的危险边界
reinterpret_cast 是唯一能将任意指针 ↔ void* 互转的 C++ cast(除 C 风格外),但它不保证可移植——特别是涉及指针大小、对齐、别名规则时。
典型高危操作:
double d = 3.14; void* p = &d; int i = *static_cast(p); // 未定义行为:读取 double 内存为 int
真正安全的场景极少,仅限:
- 把对象地址暂存为
void*,之后严格转回原类型 - 与系统 API 交互(如 Windows
LPARAM、POSIX 线程参数) - 实现内存池或自定义分配器时做原始内存管理
复杂点在于:一旦类型信息丢失,编译器无法帮你验证后续转换是否合理。它不会报错,但运行时可能崩溃或产生随机值。











