第5.11章: void*
概述
void*(读作“void 指针”)是一种能持有任何对象地址的指针,
不管该对象是什么类型。它是一个无类型指针。
由于它没有类型信息,C++ 限制了你可以对它能做的事。
在本章中,你将学到:
- 什么是
void* - 为什么
void*不能被解引用 - 为什么对
void*禁止指针算术 void*如何与 C 风格数组和退化交互- 为什么
void const*是只读内存的正确类型 - 为什么底层内存操作要使用
void*
1. 什么是 void 指针?
void* 可以存储任何对象的地址。
它是 C++ 中最通用的指针类型。
int x{42};
double y{3.14};
void *p1 = ::std::addressof(x); // ok
void *p2 = ::std::addressof(y); // ok
但由于 void* 没有类型,C++ 并不知道:
- 对象有多大
- 如何解释这些字节
- 如何执行指针算术
2. 不能解引用 void 指针
void* 不指向某个具体类型,所以 C++ 不知道
*p 该是什么意思。
void *p = ::std::addressof(x);
// *p; // ❌ error: cannot dereference void*
要访问对象,你必须把该指针转换为有类型的指针。 (转换将在后面介绍。)
3. 禁止对 void* 做指针算术
指针算术需要知道所指类型的大小。
由于 void 没有大小,算术是不允许的。
void *p = ::std::addressof(x);
// p + 1; // ❌ error: cannot do pointer arithmetic on void*
这项限制可防止意外误用。
4. void* 与 C 风格数组退化
当 C 风格数组退化时,它变成指向其首元素的指针。
这个指针可以存进 void*。
int a[3]{1,2,3};
void *p = a; // decay: a → &a[0], then stored in void*
但由于 void* 是无类型的:
- 你不能对它索引
- 你不能对它做指针算术
- 你不能解引用它
它只是一个通用地址。
5. 用 void const* 表示只读内存
当指向不得修改的内存时,请使用:
void const *p = "Hello"; // pointer to read-only memory
这遵循第2.8章的规则:
const 作用于左边。就这样。
void const* 表示“指向 const void 的指针”,
也就是“指向未知类型只读内存的指针”。
6. 为什么需要 void*
void* 用于那些事先不知道数据类型底层编程。
例如:
- 原始内存缓冲区
- 通用存储
- 与 C 库交互
- 内存操作函数(第5.14章)
void* 是一种在不携带类型信息的情况下存储“仅仅一个地址”的方式。
7. void* 并不能绕过类型系统
void* 并不能神奇地让你把内存当作任意类型使用。
它只是暂时移除了类型信息。
要使用这块内存,你必须把指针转换回正确的类型。 (转换将在后面介绍。)
8. 汇总表
| 操作 | 允许? | 原因 |
|---|---|---|
| 存储任何对象的地址 | ✔ 允许 | void* 是无类型的 |
| 解引用 | ❌ 不允许 | 没有类型信息 |
| 指针算术 | ❌ 不允许 | void 没有大小 |
| 从数组退化 | ✔ 允许 | 数组退化为 &a[0] |
| 用于只读内存 | ✔ 允许 | 使用 void const* |
要点
void*是无类型指针,可以存储任何地址。- 你不能解引用
void*。 - 你不能对
void*做指针算术。 - 只有数组的最外层维度会退化,其结果可以存入
void*。 - 只读内存请使用
void const*。 void*用于底层内存操作。void*并不能绕过类型系统;它只是暂时隐藏类型信息。