Почему я могу сделать вызов функции, используя неверный указатель класса - PullRequest
6 голосов
/ 06 октября 2009

В приведенном ниже фрагменте кода, хотя указатель не инициализирован, вызов все еще выполняется успешно

temp *ptr;
ptr->func2();

Это связано со свойством языка C ++ или это компилятор VC ++ 6, который играет нечестно?

class temp {
public:
    temp():a(9){}
    int& func1()
    {
        return a;
    }
    bool func2(int arg)
    {
        if(arg%2==0)
            return true;
        return false;
    }
    int a;
};

int main(int argc, char **argv)
{
    temp *ptr;
    int a;
    cin>>a;
    if(ptr->func2(a))
    {
        cout<<"Good poniner"<<endl;
    }
    ptr->func1(); // Does not crash here
    int crashere=ptr->func1();// But does crash here 
    return 0;
}

Ответы [ 6 ]

14 голосов
/ 06 октября 2009

Компилятор C ++ не мешает вам использовать неинициализированные указатели, и хотя результаты не определены, в реальном мире компиляторы обычно генерируют код, игнорирующий тот факт, что указатель не инициализирован.

Это одна из причин того, почему C ++ является быстрым и (сравнительно) опасным по сравнению с некоторыми другими языками.

Причина вашего звонка на func2 состоит в том, что он не касается указателя this. Значение указателя никогда не используется, поэтому оно не может вызвать проблемы. В func1 вы делаете используйте указатель this (для доступа к переменной-члену), поэтому этот сбой.

7 голосов
/ 06 октября 2009

Это полностью зависит от компилятора и неопределенное поведение в соответствии со стандартом. Вы не должны полагаться на это.

Вызов func2() успешен, потому что точный метод для вызова известен во время компиляции (вызов не виртуальный), а сам метод не разыменовывает этот указатель. Так недействительно это нормально.

ptr->func1(); // This works

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

int crashere=ptr->func1();// Crashes here

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

3 голосов
/ 06 октября 2009

C ++ имеет понятие неопределенного поведения. Использование неинициализированного указателя является типичным примером такого неопределенного поведения. Из соображений производительности стандарт C ++ не устанавливает никаких ограничений на возможный результат. То есть форматирование жесткого диска вполне приемлемо.

0 голосов
/ 06 октября 2009

Вы можете вызывать методы, используя неинициализированные указатели. Это будет работать либо ptr-> func1 (); или же int crashere = ptr-> func1 (); //

0 голосов
/ 06 октября 2009

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

0 голосов
/ 06 октября 2009

Я подозреваю, что ptr->func2() оптимизирован, поскольку он всегда возвращает true. Но, как говорит Ричи, использование указателя в этом случае прекрасно, поскольку вы не касаетесь каких-либо данных экземпляра (a), и в этом случае нечего врезаться.

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