Разыменование объекта класса nullptr

Я просматривал видео на YouTube о статике в С++, в котором я нашел фрагмент кода, который меня смущает.

#include<iostream>
using namespace std;

class Singleton {
    static Singleton* s_instance;
public:
    static Singleton& Get() { return *s_instance; }

    void display() {
        cout << "Hello" << endl;
    }

};
Singleton* Singleton::s_instance=nullptr;

int main() {
    Singleton::Get().display();
}

Интересно, почему компилятор не выдает ошибку, ведь мы возвращаем разыменованный объект nullptr в функции Get(). Кроме того, когда я пробовал то же самое, но с типом возврата функции Get(), установленным как Singleton вместо Singleton&, компилятор выдает ошибку, утверждающую, что s_instance является nullptr. Можете ли вы объяснить, имеет ли какое-то отношение к этому ссылочный тип возврата функции Get()?


person Harshabab Singh    schedule 01.07.2021    source источник
comment
Разыменование nullptr — это поведение undefined, может случиться что угодно.   -  person Quimby    schedule 01.07.2021
comment
Обратите внимание, что это не статический метод, но на самом деле он вообще не смотрит на экземпляр, на который указывает this, поэтому ему это сойдет с рук. Это по-прежнему UB, и компилятору не требуется обнаруживать или выдавать диагностику для UB.   -  person Useless    schedule 01.07.2021
comment
Часто, когда вы разыменовываете указатель, ничего заметно плохого не происходит, пока вы на самом деле не попытаетесь использовать несуществующий объект. Например, когда вы копируете его. (Разыменование указателя не обязательно требует чтения чего-либо из памяти.)   -  person molbdnilo    schedule 01.07.2021
comment
Поведение вашего кода не определено из-за разыменования нулевого указателя. Стандарт не требует диагностики (например, сообщений об ошибках или предупреждений) для неопределенного поведения.   -  person Peter    schedule 01.07.2021
comment
@molbdnilo, если я правильно понимаю, поскольку мы не возвращаем копию s_instance, таким образом, мы избегаем компилятора, выдающего ошибку, то есть наш экземпляр никогда не используется.   -  person Harshabab Singh    schedule 01.07.2021
comment
@HarshababSingh Почти, но не совсем. Компилятор не имеет ничего общего с ошибками времени выполнения. По сути, определить, является ли return *s_instance; действительным или нет, невозможно во время компиляции, поэтому компилятору не требуется выдавать ошибку или предупреждение. Но во время выполнения это выражение вызывает неопределенное поведение, что означает, что может произойти что угодно. Обычно это просто приводит к сбою, и многие системы выдают сообщение об ошибке.   -  person churill    schedule 01.07.2021
comment
Это неопределенное поведение, все может случиться. И смотрите, все равно работает! является одной из возможных вещей, которые подразумеваются под чем угодно.   -  person j6t    schedule 01.07.2021
comment
Сбои на моей машине из-за ссылки на привязку к nullptr.   -  person Eljay    schedule 01.07.2021
comment
Если вы думаете о ссылке как об указателе с другим синтаксисом (не совсем правильно, но в близком приближении), вы можете придумать причину, по которой в вашей системе возврат по ссылке был не более проблематично, чем возврат нулевого указателя. (Создание нулевой ссылки является незаконным, но в то же время компилятору не требуется добавлять проверки во время выполнения, чтобы предотвратить это.)   -  person JaMiT    schedule 02.07.2021