Skip to main content
 首页 » 编程设计

C++ Void 指针 教程

2022年07月19日115mfrbuaa

本文我们一起看看Void指针,了解它的用法及优缺点。

Void 指针

Void 指针也称为通用指针,可以指向任何类型对象的特殊类型指针。Void 指针声明与正常指针一样,使用void关键字:

void* ptr; // ptr 是Void 指针 
 

void指针可以指向任何类型对象,请看示例:

int nValue; 
float fValue; 
 
struct Something 
{ 
    int n; 
    float f; 
}; 
 
Something sValue; 
 
void* ptr; 
ptr = &nValue; // valid 
ptr = &fValue; // valid 
ptr = &sValue; // valid 
 

因为void指针不知道指向具体那种类型,直接取值是不允许的。如果需要取值,必须转换为具体类型指针。

int value{ 5 }; 
void* voidPtr{ &value }; 
 
// std::cout << *voidPtr << '\n'; // 非法: 不允许void指针直接取值 
 
int* intPtr{ static_cast<int*>(voidPtr) }; // 但可以转为int类型指针 
 
std::cout << *intPtr << '\n'; // 最后通过int指针取值,输出结果为5 

类型转换

如果不知道void指针具体为那种类型,如何进行转换呢?对,你猜对了。我们就在几种可能的类型中猜测:

#include <iostream> 
#include <cassert> 
 
enum class Type 
{ 
    tInt, // 为了避免使用关键字,因此增加前缀t 
    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: 
        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指针

void指针变量可以赋null值:

void* ptr{ nullptr };  

尽管一些编译器允许删除指向动态分配内存的void指针,但应该避免这样做,因为这可能导致不确定行为。在void指针上进行指针算术运算是不可能的,这是因为指针算法要知道所指向对象的大小,从而可适当地增加或减少指针。

注意,没有所谓的void引用,这是因为void引用的类型是void &,它并不知道引用的是什么类型的值。

  • void指针的优点
  1. Malloc()和calloc()返回void *类型,这允许这些函数用于分配任何数据类型的内存(只是因为void *)
int main(void) 
{ 
	// Note that malloc() returns void * which can be 
	// typecasted to any type like int *, char *, .. 
	int *x = malloc(sizeof(int) * n); 
} 
  1. C中的void指针用于实现C中的泛型函数

一般来说,除非绝对必要,否则避免使用void指针,这样可有效地避免类型检查。请看示例:

int nValue{ 5 }; 
printValue(&nValue, Type::tCString); 

这里类型参数不对,编译器并不检查,谁知道输出结果会是什么呢! 虽然上面的函数可以处理多个数据类型,但c++实际上提供了一种更好的方法(函数重载),它保留了类型检查,从而避免误用。许多其他地方曾经使用void指针来处理多种数据类型,现在使用模板可以更好地完成,模板也提供了强类型检查。

但在一些偶然的情况下,仍可以看到void指针的合理用途。首先要确保没有更好(更安全)的方法来使用其他机制来做同样的事情!

总结

本文通过示例了解了void指针类型。希望以后遇到能掌握其特性,但不建议太多使用。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/123791622