C++ void 指针详解

void 指针(又称泛型指针)是一种特殊指针,可指向任意数据类型的对象。其声明方式与普通指针相同,只是类型关键字为 void

void* ptr {}; // ptr 为 void 指针

void 指针能够指向任何类型的对象:

int nValue {};
float fValue {};

struct Something
{
    int n;
    float f;
};

Something sValue {};

void* ptr {};
ptr = &nValue; // 合法
ptr = &fValue; // 合法
ptr = &sValue; // 合法

然而,由于 void 指针并不知道所指向对象的具体类型,因此禁止直接解引用。必须先将其显式转换为相应类型的指针,然后才能解引用:

int value { 5 };
void* voidPtr { &value };

// std::cout << *voidPtr << '\n'; // ❌ 非法:void 指针不可解引用

int* intPtr { static_cast<int*>(voidPtr) }; // 先转换为 int*

std::cout << *intPtr << '\n'; // ✅ 合法,输出 5

程序输出:

5

随之而来的问题是:既然 void 指针不知道指向什么类型,我们怎么知道该转换成哪种指针?——最终要靠程序员自行记录。

下面是一个使用 void 指针的完整示例:

#include <cassert>
#include <iostream>

enum class Type
{
    tInt,    // 注意:此处不能使用 "int",因其为关键字,故用 "tInt"
    tFloat,
    tCString
};

void printValue(void* ptr, Type type)
{
    switch (type)
    {
    case Type::tInt:
        std::cout << *static_cast<int*>(ptr) << '\n';      // 转换为 int* 并解引用
        break;
    case Type::tFloat:
        std::cout << *static_cast<float*>(ptr) << '\n';    // 转换为 float* 并解引用
        break;
    case Type::tCString:
        std::cout << static_cast<char*>(ptr) << '\n';      // 转换为 char*,std::cout 按 C 风格字符串输出
        // 若对结果再解引用,则仅打印单个字符
        break;
    default:
        std::cerr << "printValue(): 提供的类型无效\n";
        assert(false && "type not found");
        break;
    }
}

int main()
{
    int nValue { 5 };
    float fValue { 7.5f };
    char szValue[]{ "Mollie" };

    printValue(&nValue, Type::tInt);
    printValue(&fValue, Type::tFloat);
    printValue(szValue, Type::tCString);

    return 0;
}

输出:

5
7.5
Mollie

void 指针杂项

  1. 可赋空指针值:

void* ptr { nullptr };


2. 删除 void 指针会导致未定义行为;若必须删除,应先 `static_cast` 回原类型。

3. 不允许对 void 指针进行指针算术,因为指针算术需知道所指对象大小。

4. 不存在 void 引用(`void&`),因其无法得知所引用值的具体类型。

结论  

一般而言,应尽量避免使用 void 指针,除非万不得已。void 指针绕过了类型检查,易导致无意义的操作且编译器不会报错。例如:

```cpp
int nValue { 5 };
printValue(&nValue, Type::tCString); // 合法但结果未知

尽管上述示例看似优雅,C++ 提供了更好的替代方案:

  • 函数重载可在保持类型安全的同时处理多种数据类型;
  • 模板同样能安全地实现泛型功能。

只有在确认无更安全、更合适的语言机制可用时,才应使用 void 指针。

测验

问题 #1

void 指针与空指针有何区别?

解答

void 指针是一种可指向任意类型的指针类型,其本身可为空或非空;而空指针(nullptr)是一个特殊的值,表示“不指向任何对象”。二者概念不同:

  • void 指针强调“类型未知”;
  • 空指针强调“地址为空”。

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"