何时在C++中使用void*?

11

我正在努力理解什么是 void* 以及何时适当地使用它,是否存在我应该了解的潜在不良用途(指一些酷炫的东西,而不是错误的用法)。

我不理解如何以及为什么要使用 void*。如果我理解正确,我需要将当前指针强制转换为 void*,然后在想要使用它时将其转换回原始类型...?

这有什么好处吗?并不是因为要使事情更加通用,而是需要知道传入的是什么类型的 void* 才能进行转换...

有人可以帮助我理解 void* 吗?


3
在C++中,除非是非常特殊的情况,否则永远不要使用void * - Ed Heal
1
这是其中一个“那种”特性。如果你不确定需要它,那就不需要它。 - user395760
2
如果您有一个指向多态类型对象的指针,并且想要找出包含它的最派生对象的地址,请在其上使用 dynamic_cast<void *> - Kerrek SB
1
void*在C语言中用于通用编程很有用。请看qsortbsearch。在C++中,我们有模板,每个方面都比void*更好,除了一个方面。 - Benjamin Lindley
2
啊,我记起来了:https://dev59.com/o3LYa4cB1Zd3GeqPbsvd - chris
显示剩余3条评论
2个回答

13

C语言中,使用void *相当普遍,以创建通用集合。例如,如果您想要一个通用的链表,您可以编写类似以下的代码:

typedef struct node  { 
    void *data;
    struct node *next;
} node;

那么你可以创建一个foo的链表,另一个bar的链表,以此类推。

然而,在C++中,这种方式很少有用。在典型情况下,您将想要编写等效代码作为模板:

template <typename T>
class node { 
     T data;
     node *next;
};

在旧编译器中,您可以通过结合两种技术来减少生成的代码。在这种情况下,您将使用一组指向 void 的指针来存储数据,然后有一个模板前端只处理将 T * 强制转换为 void * 以存储数据,以及从 void * 到 T * 的强制转换以检索数据。

编译器/链接器的改进使得这种技术(几乎?)完全过时了。旧编译器会为您实例化模板的每个类型生成单独的代码,即使实例化类型是不相关的。当前编译器(或工具链,无论如何 - 相当多的内容都由链接器处理)会识别相同的代码序列,并自动将它们合并在一起。

底线:除非您需要 C 兼容性,或者您正在编写替代 operator new/operator delete 的代码,否则在良好编写的 C++ 中使用 void * 通常是相当罕见的。


我建议在那些最小可寻址单元为8位的平台上使用uint8_t *,而不是void *。在我看来,指向一个8位单元比指向空指针更好。 - Thomas Matthews

4

void*是一个没有类型的内存地址。当周围代码有其他方式可以知道它所使用的类型时,它非常有用(例如,memchr需要除了地址以外还要传递内存区域的大小)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接