Всегда ли C ++ сравнивает указатель на функцию-член с 0? - PullRequest
3 голосов
/ 12 января 2011

В следующем коде утверждение не вызывается с помощью компилятора Visual Studio, но оно вызывается при компиляции для iPhone с использованием XCode:

class X
{
public:

 virtual void A() {}
};

X x;

void main()
{
 // Define a valid member function pointer to X::A.
 void (X::*p)() = &X::A;

 assert(p != 0);
}

Это ошибка в компиляторе?Как еще можно проверить нулевой указатель в этом случае?

Ответы [ 2 ]

10 голосов
/ 12 января 2011

Код правильный, компилятор не соответствует стандарту, который гласит (раздел [expr.eq], используя формулировку из C ++ 0x черновик n3225, но он должен быть таким же в других версиях):

любой указатель на член можно сравнить с константой нулевого указателя

и

Если оба операнда равны нулю, они сравниваются равными.Иначе, если только один равен нулю, они сравниваются неравно.

соответствующее определение константы нулевого указателя (раздел [conv.ptr], часть std::nullptr_t является новой в C ++ 0x):

A константа нулевого указателя - это целочисленное константное выражение (5.19) prvalue целочисленного типа, которое оценивается как ноль, или prvalue типа std::nullptr_t.

и(раздел [expr.const]):

Выражение константы - это целочисленное константное выражение, если оно имеет целочисленный или перечислимый тип.

ПРИМЕЧАНИЕ.-определенное представление указателя на функцию-член-виртуал обычно представляет собой индекс в виртуальной таблице, который будет равен 0 в вопросе.Но согласно стандарту, выражение внутри assert не проверяет, является ли представление нулевым, оно проверяет нулевой литерал - это проверка нулевого указателя.

И компилятор Apple, очевидно, смешал двавверх.Если вы хотите проверить, является ли представление нулевым, вы могли бы написать assert((intptr_t)p != 0) - и это было бы полностью непереносимым.

Но код в том виде, как он написан, совершеннопереносимый на любой совместимый со стандартом компилятор, и никогда не будет утверждать .

РЕДАКТИРОВАТЬ: И еще одна цитата из стандарта, которая просто повторяет то, что мы уже изучили (раздел [conv.mem]):

Константа нулевого указателя (4.10) может быть преобразована в указатель на тип члена;результатом является значение указателя нулевого элемента этого типа, которое отличается от любого указателя на элемент, не созданный из константы нулевого указателя.

3 голосов
/ 12 января 2011

Компилятор iPhone ошибается.

Обратите внимание, что сравнение на равенство между указателями на функции-члены, которые указывают на виртуальные функции , дает неопределенный результат, т.е.

assert(&X::A == &X::A);

ведет себя непредсказуемо с формальной точки зрения.

Но сравнение указателей на функции-члены с константой нулевого указателя строго определяется языком. Указатель не может быть нулевым в вашем примере, поэтому он не должен сравниваться с константой нулевого указателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...