(void *)1 是什么意思?

What does (void *)1 mean?

我正在阅读 ROS 的代码。

在文件ros_comm/roscpp/include/ros/subscriber.h中,我看到了这样一段代码:

operator void*() const { return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; }

嗯,(void *)0在C中可以看做是NULL,但是(void *)1是什么意思呢?

如果一个classFoo包含这个函数,就意味着我们可以这样编码:

Foo foo;
void *ptr = foo;

对吧?那么是不是说 void *ptr = (void *)1 可以呢?这是什么意思?

这是一个老技巧,可以避免在 C++11 中引入 explicit 上下文转换之前隐式转换为 bool 的问题。它旨在用于检查有效性:

Subscriber my_subscriber = someFunction();
if (!my_subscriber) {
    // error case
}

重要的一点是不存在从 void* 到整数类型的 built-in 转换,但存在从 bool 到整数类型的转换。同时,存在从 void*bool 的 built-in 转换。这意味着如果您将隐式转换定义为 bool,则以下内容出人意料地有效:

void my_func(int i);

void another_func() {
    Subscriber sub = something();
    my_func(sub);
}

将转换定义为 void* 可避免该问题。


不过现在这个技巧已经过时了。 C++11 引入了 explicit 转换。 explicitbool 的转换在 if 和循环的条件下被考虑,但在其他有问题的情况下不被考虑。这意味着现在转换应该写成:

explicit operator bool() const { return impl_ && impl_->isValid(); }

这表明编写代码的人不是很熟悉他们使用的语言或工具,或者代码已经存在了很长时间并且被不同的人攻击过,大概在过去的某个时间经历了 C-to-C++ 过渡,仍然携带着一些遗留的 API 合同(期待 void*),这可能很难改变。

没有好的理由做这样的事情,如果你看看源代码。 impl_ 是一个 boost::shared_ptr<Impl>,它实现了 operator boolImpl::isValid returns bool。除了 bool 以外,没有理由在任何地方使用或 return。

基本上,这是一种扭曲的(并且可能是危险的)写作方式:

return impl_ && impl_->isValid();