一、void*
是什么?
在 C/C++ 中,void*
表示一个通用指针类型(generic pointer),可以指向任意类型的对象,但 不能直接解引用或进行算术运算,必须先进行类型转换。
void* ptr; // 可以指向任意类型,但不能直接使用
二、常见用途
1. 通用函数参数(例如 C 风格 API)
void printValue(void* data, char type) {
if (type == 'i') {
std::cout << *(int*)data << std::endl;
} else if (type == 'f') {
std::cout << *(float*)data << std::endl;
}
}
2. C 接口中的回调函数传参
如 pthread_create()
或一些库函数会使用 void*
传递参数。
void* myThreadFunc(void* arg) {
int* data = (int*)arg;
std::cout << "Thread data: " << *data << std::endl;
return nullptr;
}
3. 动态内存和数据结构封装(如 C 语言实现链表)
三、使用 void*
的注意事项
注意点 | 说明 |
---|---|
❌ 不可解引用 | *ptr 是非法的,除非转换为具体类型:*(int*)ptr |
❌ 不知道大小 | sizeof(void*) 是指针大小,而非它指向的对象大小 |
❌ 不能做指针运算 | 如 ptr + 1 是非法的 |
✅ 必须手动强制转换 | 使用前必须 static_cast 或 C 风格强制类型转换 |
✅ 避免在现代 C++ 中滥用 | 优先考虑模板、std::variant 或虚函数代替 |
四、C++ 示例代码(完整示范)
#include <iostream>
#include <string>
void printValue(void* data, char type) {
switch (type) {
case 'i':
std::cout << "int: " << *(int*)data << std::endl;
break;
case 'f':
std::cout << "float: " << *(float*)data << std::endl;
break;
case 's':
std::cout << "string: " << *(std::string*)data << std::endl;
break;
default:
std::cout << "Unknown type" << std::endl;
}
}
int main() {
int i = 42;
float f = 3.14f;
std::string s = "Hello";
printValue(&i, 'i');
printValue(&f, 'f');
printValue(&s, 's');
return 0;
}
输出:
int: 42
float: 3.14
string: Hello
五、现代 C++ 替代方案
现代 C++ 不推荐频繁使用 void*
,可替代选项包括:
替代方式 | 说明 |
---|---|
std::any |
任意类型存储,类型安全但有开销 |
std::variant |
类型受限但更高效,适合多类型分发 |
模板泛型 | 用于写通用函数,如 template<typename T> |
虚函数 + 多态 | 对象行为抽象,面向对象设计更合理 |
总结
优点 | 缺点 |
---|---|
通用性强、兼容 C 接口 | 安全性差、容易出错 |
简洁灵活 | 类型信息丢失、无法自动类型推导 |
在 写 C++ 项目时不建议广泛使用 void*
,但在与底层 C 库、系统 API 交互时,它仍是不可或缺的手段。