((SA*)0)->Func();
От: Андрей Тарасевич Беларусь  
Дата: 29.04.02 18:05
Оценка: 9 (2)
#Имя: FAQ.cpp.*nullptr
DG>Должен ли по стандарту работать следующий код?

struct SA
{
  void Func() //невиртуальная
  {
    if (this == NULL) 
      return;
  }  
  static void StaticFunc() {}
};

void main()
{
  ((SA*)0)->StaticFunc(); //ИМХО, тут должно быть все нормально
  ((SA*)0)->Func(); //а вот здесь не понятно, мало ли чего может компилятор напихать
}


DG>Написано ли где-нибудь в стандарте, что компилятор не должен закладываться на то, что this всегда не равен нулю?


АТ>>Может написано, может не написано. Это, в принципе, неважно. Стандарт вместо этого совершенно глухо запрещает все возможные пути попадания внутрь метода объекта через null-указатель. А именно: запрещается разадресовывать null-указатель. Это автоматически означает, что, пока поведение программы определено, внутри метода объекта this никак не может быть равен null-указателю.


ПК>AFAIK, вызов метода сам по себе не подразумевает разыменования указателя. Поэтому в стандарте (9.3.1/1) явно указано, что "If a nonstatic member function of a class X is called for an object that is not of type X, or of a type derived from X, the behavior is undefined". Т.к. null-pointer гарантированно не является указателем ни на какой объект, это предложение включает и вызов метода через null-pointer.


Я не согласен. Возможность вызова метода класса (причем как статического, так и нестатического) через null-указатель перекрыта стандартом еще раньше. Стандарт языка подчеркивает, что выражение, стоящее слева от '.' или '->' при доступе к члену класса (методу или полю), обязательно вычисляется. Причем оно вычисляется независимо от того, является ли доступаемый член класса статическим или нет. Вычисление этого выражения автоматически означает разыменование использованного в нем указателя. Разыменование null-указателя порождает неопределенное поведение.

Из приведенной тобой выдержки, кстати, может показаться, что к статическим членам класса можно доступаться через null-указатель. Это не так. Любое вычисляемое выражение, содержащее разыменование null-указателя порождает неопределенное поведение. А вот например параметр 'typeid' может содержать разыменованный null-указатель, т.к. выражение-параметр 'typeid' не вычисляется.

Также можно заметить, что если бы вызов метода не подразумевал разыменования указателя, то стандарт языка С++ должен был бы содержать отдельное замечание по поводу вызова виртуальных методов. Эти последние вызывать через null-указатель все таки нельзя (мы все в глубине души знаем, что такой вызов существенно подразумевает разыменование указателя). Я не нашел в стандарте такого замечания.
Best regards,
Андрей Тарасевич
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.