const void的作用是什么?

67

显然,可以声明一个返回 const void 的函数:

const void foo()
{
}

由于以下代码无法编译,因此g++似乎认为const很重要:

#include <type_traits>

static_assert(std::is_same<void(), const void()>::value, "const matters");

那么,const void 有任何实际意义吗?


7
没有具体情况的情况下,我会说它是出于正交性的原因而存在。想象一下一个元函数,它替换类型但不替换限定符。它将适用于所有类型,除了如果void可以隐式地被去掉,那么它就不能使用void。 - ltjax
1
我现在很好奇是什么导致了这个发现。 :) 你在玩编译器的中间输出,是吗? - Tim Post
@Tim:我试图决定在函数指针查找表中放置常量的位置。有三个可能的位置。其中一个无法编译,最外层的“const”清楚地声明了返回“const void”的函数指针数组,我很惊讶编译器接受了这段代码。 - fredoverflow
2
cdecl.org 对于偶尔需要询问“这个限定符应用于什么?”的时候是有用的。 - John Bartholomew
2个回答

50
并不完全是这样。但是忽略void类型上的cv修饰符或将其视为错误可能会在编译器实现和最终用户代码方面产生不必要的复杂性。考虑像模板这样的内容。
  template<typename T>
  const T ...

在那种情况下,没有理由使使用 void 成为一个特殊情况(比它已经是的更加特别),这只会带来麻烦。

另外,虽然 const void 没有用处,但是 const void* 有其用途。


2
const void * 有多大用处?我可以理解 void * const 的用法,但前者不太明白。 - Spidey
6
您可以使用它来保留常量性(const-ness)并在通过 void* 地带回时保持不变。 string read_name(enum dynamic_type, const void*)。虽然不是非常有用,但比 const void 更有用。当然,void* const 也很有用,但这与问题无关。 - Logan Capaldo
1
@Spidey 如果你已经在做像将指针(一些 T*)强制转换为 void*(然后再转回来)这样的事情,那么 const void* 就是 const 等效的类型(对于一些 const T*)。当然,你可以使用 const_cast 来去除它,但为什么呢?换句话说,它与任何其他 const T* 一样有用,而且这很有用。 :) - Lightness Races in Orbit

15

const void被允许,因为没有必要让编译器对一个普遍规则做出一个特殊的例外,而且保留它也不会有什么害处。

上面有一些关于const void*不是很有用的讨论:

const void *有多有用?我能看出void * const可能有用,但前者不行。 -Spidey

实际上,const void*有时是必要的。 它声明所指的内容是只读的,与之相反的是void* const,它只声明指针本身是常量,但并不是它所指的东西是常量。

从我的经验来看,使用const void*作为指向常量的指针是这两种形式中更有用的。当然,还有const void* const,表示指针和它指向的内容都是常量。

void*通常用作传递非具体指针的方法(例如,使用memcpy())。 如果你想将const char*传递给这样的函数,那么你不能使用void*,否则你将失去它指向的内容是常量且不能被改变的事实。当前的C++编译器将拒绝编译,因为它必须隐式地强制转换掉const,这样做是正确的,因为这些数据可能在只读内存中,并且如果任何东西尝试写入它,可能会导致异常。

这就是为什么memcpy()的第二个参数是const void*而不是简单的void*


提示:请用反引号替换单引号。 - Karoly Horvath

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