Может ли указатель NULL после «dynamic_cast» фактически быть разыменован? - PullRequest
4 голосов
/ 06 июня 2011

Следующий код правильно компилируется и получает загадочный вывод:

специальная функция инвестиций 00000000

(среда: C ++ VS2010)

#include <iostream>
#include <vector>
using namespace std;

class Security {
public:
  virtual ~Security() {}
};

class Stock : public Security {};

class Investment : public Security {
public:
  void special() {
    cout << "special Investment function" << endl;
  }
};

int main() {
  Security* p = new Stock;
  dynamic_cast<Investment*>(p)->special();
  cout << dynamic_cast<Investment*>(p) << endl;
  return 0;
}

Как это могло произойти?Разыменование нулевого указателя и получение «правильного» вывода вместо сбоя?Это особая «характеристика» VS2010?

Теперь я вижу.Я сделал тест, и кажется, что разыменование «this» в «special» функции вызывает сбой программы.

Спасибо за вашу помощь.

Ответы [ 8 ]

7 голосов
/ 06 июня 2011

Разыменование нулевого указателя - неопределенное поведение - вы можете получить неожиданные результаты. Смотрите этот очень похожий вопрос .

В этом случае Investment::special() вызывается не виртуальным способом, поэтому вы можете думать, что компилятор просто создает глобальную функцию

Investment_special_impl( Investment* this )

и вызывает его, передавая нулевой указатель this в качестве неявного параметра.

Не стоит полагаться на это.

4 голосов
/ 06 июня 2011

Это «неопределенный bahviour». Думайте о методах как о неявных параметрах, несущих «это». В вашем случае NULL был передан в качестве фактического аргумента для этого. Поскольку вы не ссылались ни на какие объектные данные, на которые ссылаются (неявно или явно) с помощью «this», это не привело к сбою.

Если бы метод был виртуальным, он, скорее всего, потерпел бы крах, поскольку виртуальные вызовы часто отправлялись через таблицу поиска, связанную с объектом (и, как следствие, 'this').

Поскольку авторы компилятора могут свободно реализовывать таблицы поиска this и virtual, как им угодно, вы не должны зависеть от этого поведения. Не определено.

2 голосов
/ 06 июня 2011

Нигде здесь вы не разыменовываете нулевой указатель: вы просто вызываете функцию Investment :: special (NULL), которая не является виртуальной, и в своем теле не разыменовывает это. Хотя спецификация, вероятно, говорит, что это неопределенное поведение, со стороны компилятора совершенно разумно не помещать здесь разыменования, чтобы программа не вылетала.

2 голосов
/ 06 июня 2011

В большинстве реализаций C ++ не виртуальные методы не требуют вызова действительного экземпляра (быстрее не проверять this, поскольку стандарт не требует этого).

Вы можете установить указатель в NULL, и метод все равно будет успешным, если вы не получите доступ к полям экземпляра.

Виртуальные методы требуют допустимого vtable, поэтому они всегда разыменовывают объект и вызывают ошибку, если он не инициализирован.

1 голос
/ 06 июня 2011

Вы НЕ должны разыменовывать указатель NULL, так как это может привести к неопределенному поведению.Почему ваш код работает, потому что в методе:

void special() {
  cout << "special Investment function" << endl;
}

Вы действительно не ссылаетесь на this.Чтобы продемонстрировать это, просто объявите переменную внутри класса Investment и попробуйте распечатать ее внутри special().Вы получите крах.

1 голос
/ 06 июня 2011

Разыменование любой Указатель NULL имеет неопределенное поведение.

0 голосов
/ 06 июня 2011

Я не уверен насчет вопроса разыменования NULL, но поведение кода я могу объяснить.

dynamic_cast (p) -> special ();

отпечатки: «специальная инвестиционная функция»

cout << dynamic_cast <Investment *> (p) << endl; </strong>

печатает: "0xABABABA" <- адрес памяти экземпляра p </p>

Это похоже на бег:

cout << p << endl; </p>

0 голосов
/ 06 июня 2011

Разыменование нулевого указателя вызывает неопределенное поведение, независимо от того, как получить нулевой указатель, в результате dynamic_cast или чего-то еще.

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