void指针不能直接解引用或算术运算,必须显式转换为具体类型指针才能安全使用,适用于C接口对接等低层场景,现代C++应优先用模板、std::any等类型安全机制替代。

void指针不能直接解引用,必须先强制转换类型
这是最常踩的坑:写 *ptr(其中 ptr 是 void*)会编译失败,因为编译器不知道该按几个字节读、怎么解释内存。C++ 不允许对 void* 做算术运算或解引用,它只是“指向某处”的占位符。
正确做法是明确知道原始类型后,用 static_cast 转回原类型指针再操作:
int x = 42; void* p = &x; int* ip = static_cast<int*>(p); // 必须显式转换 std::cout << *ip << "\n"; // 输出 42
- 绝对不要用 C 风格的
(int*)p—— 它绕过类型检查,容易掩盖错误 - 如果原始类型未知或不固定,
void*就不该用于数据访问,考虑用std::any或模板替代 - 转换前必须确保
p确实指向该类型的对象,否则行为未定义
void指针适合做“类型擦除”的临时容器,但仅限于已知生命周期的场景
典型用途是函数参数中接收任意类型地址,比如系统 API(qsort 的 base 参数)、回调上下文(pthread_create 的 arg)或简易内存池分配器的返回值。
关键约束是:你得自己管理类型信息和对象生命周期。
立即学习“C++免费学习笔记(深入)”;
- 传入
void*前,确保所指对象在使用期间不会被销毁(例如别传局部变量地址给异步回调) - 不要把
void*当通用容器长期持有——没有类型信息,无法安全析构或拷贝 - 若需保存类型,常见做法是配套传一个
enum或函数指针(如destroy_fn),但 C++ 中更推荐用std::variant或std::function
void指针与const限定符组合时,const位置决定可修改性
void const*(等价于 const void*)表示“指向常量的 void 指针”,即不能通过它修改所指内容;而 void* const 表示“常量 void 指针”,指针本身不可变,但内容可改。
实际中几乎只用 const void*,比如 memcpy 的第一个参数:
char buf[10]; memcpy(buf, "hello", 5); // 第二个参数是 const void*
- 如果你要传递只读数据,务必声明为
const void*,避免调用方意外修改 -
const void*可隐式转为void*吗?不能——C++ 禁止丢弃 const,必须用const_cast(但应尽量避免) - 对
const void*解引用仍需先转成带 const 的具体类型,如static_cast<const int*>(p)
现代C++中,void指针大多可被模板或类型安全机制替代
除了对接 C 接口或极低层操作(如自定义分配器的 allocate 返回 void*),日常开发中应优先避开 void*。
- 泛型逻辑用模板:比如
template<typename T> void process(T* p)比void* p+ 类型标签更安全 - 运行时多态用
std::any(单值)或std::variant(有限类型集合) - 回调上下文可用
std::function包装捕获,而不是塞void*进去再强转 - 注意:标准容器(如
std::vector<char>)和std::span已能覆盖大部分“原始内存块”场景
真正难处理的点从来不是语法,而是谁负责释放内存、类型信息存在哪、以及转换发生在哪一层——这些都得靠人工约定,void* 本身不提供任何保障。


















