前言:在C/C++中,void*指针因其能够指向任意类型数据,常被称作“万能指针”或“通用指针”。实际上,它并非真正的“万能”,使用需格外小心。它是底层编程的利器,同样也是 bug 的重灾区。
目录
一、void* 指针概念
二、void* 指针的典型应用场景
2.1 memcpy/memset内存操作
2.2 函数的通用参数
2.3 与C库或底层系统交互
三、void* 指针的一些限制与陷阱
3.1 不能直接解引用
3.2 不支持算术运算
3.3 类型安全缺失
3.4 内存管理陷阱
四、现代C++的替代方案
4.1 模板
4.2 智能指针
4.3 std::any
童鞋们,有没有过这样的经历:代码中无意中用了void* 指针,突然程序就崩溃了,查了半天找不到原因。头大。。。。
int main() {
MyClass* obj = new MyClass();
void* p = obj;
delete p;
return 0;
}
比如上述代码,很多童鞋估计踩过这样的坑。别担心,今天教大家如何避坑。
一、void* 指针概念
void* 是一种特殊的指针类型,被称为“无类型指针”。它可以指向任何数据类型,其本质是仅存储对象的内存地址,而不携带该对象的类型信息。这种设计使 void* 能够在不知道具体数据类型的情况下存储和传递对象的地址,从而实现一定程度的泛型编程能力。
void* 指针与其他类型指针的赋值规则:
1)其它类型指针 -> void* 指针
任何其它类型的指针都可以直接赋值给 void* 指针,无需强制类型转换。因为“无类型”可以包容“有类型”。
int a = 10;
void* p = &a; // 正确:int* 可以隐式转换为 void*
2)void* 指针 -> 其它类型指针
void* 指针赋值给其它类型的指针则必须进行显式类型转换。因为“有类型”不能自动包容“无类型”。
void* p = &a;
int* p2 = (int*)p; // 正确:通过强制转换将 void* 转为 int*
二、void* 指针的典型应用场景
虽然void* 指针存在潜在风险,但其在 C 语言和一些底层 C++ 编程中仍然扮演着重要角色。其典型应用包括:
2.1 memcpy/memset内存操作
在 C 语言中,void* 常用于实现可以处理不同数据类型的通用函数。例如,memcpy() 和 memset() 等标准库函数。可以透明地操作内存,而无需关心实际存储的数据类型。
void* memcpy(void* dest, const void* src, size_t num);
void* memset(void* buffer, int c, size_t num);
2.2 函数的通用参数
当函数需要处理未知类型的数据时,可以使用 void* 作为参数类型,使函数能够接受任意数据类型的指针。例如:一个通用“打印函数”:





