Pytanie Odwołanie nie może mieć wartości NULL lub może mieć wartość NULL?


Czytałem z Wikipedii, że:

"Referencje nie mogą być puste, podczas gdy wskaźniki mogą; każde odniesienie odnosi się do jakiegoś przedmiotu, chociaż może on być ważny lub nie. "

Ale nie wierzę ze względu na następujący kod spójrz na to kompilator nie daje żadnego błędu:

class person
{
public:
virtual void setage()=0;
};
main()
{
person *object=NULL;
person &object1=*object;
}

Proszę rozwinąć ten punkt.


9
2018-01-29 20:52


pochodzenie


Artykuł powinien prawdopodobnie powiedzieć: "Każde odniesienie w dobrze uformowanym programie odnosi się do obiektu". Dereferencja wskaźnika zerowego jest oczywiście źle sformułowana. - GManNickG
I nie zapominajmy o naszej ulubionej historii o zerowych referencjach: gotw.ca/conv/002.htm - GManNickG
@GMan: Brzmi lepiej dla mnie. I LOLed w połączonym GOTW. "Nie mogę go uczyć, pociąga go niezdefiniowane zachowanie:" niestety, znam takich ludzi. - James McNellis
Oczywiście program jest źle uformowany. Głównie z powodu zaginionych int. - avakar
Nie ponownie ... kolejna dyskusja o zerowym odwołaniu ... Standard wyraźnie stwierdza (8.3.2 / 4) "referencja zerowa nie może istnieć w dobrze zdefiniowanym programie" - David Rodríguez - dribeas


Odpowiedzi:


Powiedzenie person &object1=*object to nie to samo, co mówienie person &object1=NULL. Prawdopodobnie kompilator nie jest wystarczająco inteligentny, aby dowiedzieć się, że usuwasz zerowy wskaźnik, ale i tak dostaniesz błąd runtime. Tak więc są one nadal prawdziwe;)


9
2018-01-29 20:57



ok ok i zrozumiałem twój punkt bardzo wyraźnie dziękuję - Zia ur Rahman


W twoim kodzie:

person *object=NULL;
person &object1=*object;

wyłuskujesz wskaźnik NULL, więc dostajesz niezdefiniowane zachowanie. Aby odpowiedzieć na twoje pytanie, nie ma czegoś takiego jak referencja NULL.

Aby zająć się drugą częścią twojego pytania, tylko dlatego, że program się kompiluje, nie ma gwarancji, że jest poprawna lub że będzie działać. Kompilatory C ++ nie muszą nawet próbować zdiagnozować rodzaju błędu, który zawiera twój kod.


20
2018-01-29 20:55





Możesz mieć referencję zerową, nie wiesz, dlaczego ktoś powiedziałby inaczej, jest to nieprzyjemny efekt uboczny niektórych operacji. Po prostu nie możesz go utworzyć bezpośrednio.


4
2018-01-29 22:20



Nie powinienem się dziwić, że widzę w tekście, zawsze mogę powiedzieć, co wyruszy na głupich ludzi na planecie, którzy myślą, że wiedzą wszystko, ale nic nie wiedzą. - Charles Eli Cheese
Możesz uzyskać NULL referencje w praktyce. Kiedykolwiek ktoś mówi: "ty żargon mieć NULL referencje ", powinien przeczytać w dobrze uformowanym programie. Oprócz wykreślania wskaźników NULL, możliwe jest również utworzenie odwołania, dzięki czemu &ref == NULL wykonując inicjalizację: int& ref = ref; (wynik może być cokolwiek, w tym NULL, jak przypuszczam). - Nie sądzę, że byłoby coś złego, jeśli chodzi o pragmatyczny aspekt problemu, ale twoja odpowiedź jest niejasna, nieinformatywna i kłótliwa ("pomimo tego, co wszyscy mówią, [nieco bełkotu tutaj wskazują")). - UncleBens
@Wujek Ben, Zero odniesienie ma konotacje, które nie są obsługiwane przez język. Myślę nieważny odniesienie lepiej opisuje sytuację. To subtelna różnica, ale uważam, że jest mniej kontrowersyjna. - Mark Ransom


to zawiedzie twój program. Czy próbowałeś go uruchomić? wykonanie obiektu * spowoduje, że dany wskaźnik zostanie odrzucony, więc Twoje odniesienie nigdy nie zostanie przypisane.


3
2018-01-29 20:56



Odpowiedź była zrozumiała. - Zia ur Rahman
Nie sądzę, żeby to się zawiesiło. Spowoduje to awarię tylko wtedy, gdy spróbujesz uzyskać dostęp do członków (lub metod) obiektu1. - Julio
Może się zawiesić, wydrukować 42 lub emitować niebieski dym - po prostu wykreślanie zerowego wskaźnika wywołuje niezdefiniowane zachowanie, więc nie możesz tego z góry wiedzieć. - Georg Fritzsche
Właśnie próbowałem z GCC. Stworzyłem "odwołanie NULL" do napisu bez słowa z kompilatora. Otrzymano błąd segmentacji z GDB tylko podczas próby wywołania funkcji składowej. IMO, podczas gdy technicznie "nie możesz mieć" NULL referencje, ważne jest, aby być świadomym problemów, gdy coś nie idzie dobrze. - W każdym razie odpowiedź jest błędna. Jeśli zachowanie czegoś jest niezdefiniowane, nie ma gwarancji, że ulegnie awarii. - UncleBens


Cóż, możesz zrobić cokolwiek ty chcę w C ++. Inny przykład:

person &object1 = *( reinterpret_cast<person*>(0) );

Wywołujesz niezdefiniowane zachowanie w powyższym przypadku, oprócz przypadku, o którym wspomniałeś!


2
2018-01-29 20:55



Dzięki Neil, poprawiłem to. - AraK
Czy jest jakiś powód, dla którego wolisz reinterpret_cast do a static_cast? (Zachowują się tak samo w tym przypadku oczywiście). - avakar
@avakar To, co przyszło mi do głowy, kiedy napisałem odpowiedź :) - AraK


clang 3.5 ostrzega nawet o możliwym późniejszym sprawdzeniu referencji przez NULL:

/tmp/person.C:11:6: warning: reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to
      always convert to true [-Wundefined-bool-conversion]
if (&object1) {}
~~   ^~~~~~~
1 warning generated.

0
2017-12-20 18:35