Что означает (void *) 1? - PullRequest
       55

Что означает (void *) 1?

39 голосов
/ 10 июля 2019

Я читаю код ROS .

В файле ros_comm/roscpp/include/ros/subscriber.h я вижу такой кусок кода:

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

Ну,(void *)0 можно рассматривать как NULL в C, но что означает (void *)1?

Если класс Foo содержит эту функцию, это означает, что мы можем кодировать так:

Foo foo;
void *ptr = foo;

Верно?Значит ли это, что void *ptr = (void *)1 возможно?Что это значит?

Ответы [ 2 ]

60 голосов
/ 10 июля 2019

Это старый трюк, позволяющий избежать проблем с неявными преобразованиями в bool до того, как в C ++ 11 были введены explicit контекстные преобразования.Он предназначен для проверки правильности:

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

Важным моментом является то, что не существует встроенного преобразования из void* в целочисленные типы, но существует одно из bool в целочисленные типы.В то же время существует встроенное преобразование из void* в bool.Это означает, что если вы определяете неявное преобразование в bool, то удивительно верно следующее:

void my_func(int i);

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

Определение преобразования в void* позволяет избежать этой проблемы.


В наши дни этот трюк устарел.C ++ 11 ввел explicit преобразований.explicit преобразования в bool рассматриваются в условиях if и циклов, но не рассматриваются в других проблемных случаях.Это означает, что в наши дни это преобразование должно быть записано как:

explicit operator bool() const { return impl_ && impl_->isValid(); }
0 голосов
/ 10 июля 2019

Это показывает, что либо человек, который написал код, не очень хорошо знаком с языком или инструментами, которые они используют, либо код был долгое время долгое время и был взломан разными людьми, предположительно претерпев переход C-to-C ++ в прошлом, он все еще переносил некоторый устаревший контракт API (ожидая void*), который может быть проблематичным для изменения.

Нет хороших причин делать такие вещи, если вы посмотрите на источник. impl_ - это boost::shared_ptr<Impl>, который реализует operator bool, а Impl::isValid также возвращает bool. Нет никаких причин использовать или возвращать что-либо, кроме bool в любом месте.

По сути, это искаженный (и, возможно, опасный) способ написания:

return impl_ && impl_->isValid();
...