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 <ul> <li>绝对不要用 C 风格的 <code>(int*)p</code> —— 它绕过类型检查,容易掩盖错误</li> <li>如果原始类型未知或不固定,<code>void*</code> 就不该用于数据访问,考虑用 <code>std::any</code> 或模板替代</li> <li>转换前必须确保 <code>p</code> 确实指向该类型的对象,否则行为未定义</li> </ul> <h3>void指针适合做“类型擦除”的临时容器,但仅限于已知生命周期的场景</h3> <p>典型用途是函数参数中接收任意类型地址,比如系统 API(<code>qsort</code> 的 <code>base</code> 参数)、回调上下文(<code>pthread_create</code> 的 <code>arg</code>)或简易内存池分配器的返回值。</p> <p>关键约束是:你得自己管理类型信息和对象生命周期。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a> <p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p> </div> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <ul> <li>传入 <code>void*</code> 前,确保所指对象在使用期间不会被销毁(例如别传局部变量地址给异步回调)</li> <li>不要把 <code>void*</code> 当通用容器长期持有——没有类型信息,无法安全析构或拷贝</li> <li>若需保存类型,常见做法是配套传一个 <code>enum</code> 或函数指针(如 <code>destroy_fn</code>),但 C++ 中更推荐用 <code>std::variant</code> 或 <code>std::function</code> </li> </ul> <h3>void指针与const限定符组合时,const位置决定可修改性</h3> <p><code>void const*</code>(等价于 <code>const void*</code>)表示“指向常量的 void 指针”,即不能通过它修改所指内容;而 <code>void* const</code> 表示“常量 void 指针”,指针本身不可变,但内容可改。</p> <p>实际中几乎只用 <code>const void*</code>,比如 <code>memcpy</code> 的第一个参数:</p> <pre class="brush:php;toolbar:false;">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)</const>
现代C++中,void指针大多可被模板或类型安全机制替代
除了对接 C 接口或极低层操作(如自定义分配器的 allocate 返回 void*),日常开发中应优先避开 void*。
- 泛型逻辑用模板:比如
template<typename t> void process(T* p)</typename>比void* p+ 类型标签更安全 - 运行时多态用
std::any(单值)或std::variant(有限类型集合) - 回调上下文可用
std::function包装捕获,而不是塞void*进去再强转 - 注意:标准容器(如
std::vector<char></char>)和std::span已能覆盖大部分“原始内存块”场景
真正难处理的点从来不是语法,而是谁负责释放内存、类型信息存在哪、以及转换发生在哪一层——这些都得靠人工约定,void* 本身不提供任何保障。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










