Właściwości wskaźnika do tablicy zerowej długości

21

Rozważać

int main()
{
    auto a = new int[0];
    delete[] a; // So there's no memory leak
}

Czy między inicjowaniem i usuwaniem kopii można odczytywać wskaźnik w a + 1?

Ponadto, nie pozwalają na język kompilator zestaw ado nullptr?

Batszeba
źródło
2
@ Fareanor: Możesz ana pewno czytać (z pewnością nie możesz tego wyrejestrować).
Batszeba
8
@RasmiRanjanNayak: To pranie.
Batszeba
2
@RasmiRanjanNayak O mój ... nie
Ted Lyngmo
1
@TedLyngmo: Kiedy mówię „przeczytaj wskaźnik w a + 1”, czy następujący kod jest auto b = a + 1;niezdefiniowany? (Myślę, że to jest).
Batszeba
2
@Ayxan zgaduję, że w 0rzeczywistości jest to wynik wyrażenia, którego nie poznasz do czasu uruchomienia. Ponieważ new int[0]jest bezpieczny, może zaoszczędzić Ci martwienia się o niektóre rozgałęzienia / przypadki specjalne. Wyobraź sobie, że miałbym zainicjować za std::vectorpomocą std::vector<int> v(0);.
scohe001

Odpowiedzi:

3
    auto a = new int[0];

Zgodnie z [basic.compound.3] przechowywana wartość amusi być jedną z następujących czynności:

  1. Wskaźnik do obiektu (typu int)
  2. Wskaźnik za końcem obiektu
  3. Zero
  4. Nieważny

Możemy wykluczyć pierwszą możliwość, ponieważ nie zbudowano żadnych obiektów typu int. Trzecia możliwość jest wykluczona, ponieważ C ++ wymaga zwrotu niepustego wskaźnika (patrz [basic.stc.dynamic.allocation.2] ). Mamy zatem dwie możliwości: wskaźnik za końcem obiektu lub nieprawidłowy wskaźnik.

Byłbym skłonny postrzegać ajako wskaźnik przeszłości, ale nie mam renomowanego odniesienia, aby definitywnie to ustalić. (Istnieje jednak silna implikacja tego w [basic.stc] , widząc, jak można deleteten wskaźnik.) W związku z tym przedstawię obie możliwości.

Czy między inicjowaniem i usuwaniem kopii można odczytywać wskaźnik w a + 1?

Zachowanie jest niezdefiniowane, jak podyktowane jest to [expr.add.4] , niezależnie od tego, która z powyższych możliwości ma zastosowanie.

Jeśli awskaźnik jest końcowy, uważa się, że wskazuje hipotetyczny element na indeks 0tablicy bez elementów. Dodanie liczby całkowitej jdo ajest definiowane tylko wtedy 0≤0+j≤n, gdy , gdzie njest rozmiar tablicy. W naszym przypadku nwynosi zero, więc suma a+jjest definiowana tylko wtedy, gdy jjest 0. W szczególności dodawanie 1jest niezdefiniowane.

Jeśli ajest nieważny, wówczas czysto popadamy w „W przeciwnym razie zachowanie jest niezdefiniowane”. (Nic dziwnego, że zdefiniowane przypadki obejmują tylko prawidłowe wartości wskaźnika).

Ponadto, nie pozwalają na język kompilator zestaw ado nullptr?

Nie. Z wyżej wspomnianego [basic.stc.dynamic.allocation.2] : „Jeśli żądanie powiedzie się, wartość zwrócona przez wymienną funkcję alokacji jest wartością wskaźnika o wartości innej niż zero” . Istnieje również przypis wzywający, że C ++ (ale nie C) wymaga niepustego wskaźnika w odpowiedzi na żądanie zerowe.

JaMiT
źródło
1
Jeśli byłaby
TC
@TC Prawda, co oznacza, że ​​nie może to być niepoprawna wartość wskaźnika.
JaMiT
23

Na podstawie ostatniej dyskusji odbłyśnika CWG w wyniku wydania redakcyjnego 3178new int[0] produkuje to , co obecnie nazywa się „past-the-end” wartość wskaźnika .

Wynika z tego, że anie może być zerowy i a + 1jest niezdefiniowany przez [expr.add] / 4 .

TC
źródło
4
„Na podstawie ostatniej dyskusji na temat reflektorów CWG w wyniku wydania redakcyjnego 3178 new int[0]powstaje tak zwana wartość wskaźnika„ z przeszłości ”. Nie jest to dokładne. Nie było dużo dyskusji. Jedna osoba zasugerowała, że ​​wartość powinna być „wskaźnikiem za końcem obiektu”, a to stwierdzenie zostało zakwestionowane, ponieważ w przypadku tablicy z 0elementami nie ma obiektu, który mógłby zostać przekroczony.
Lawyer językowy
@LanguageLawyer nie ma wątpliwości, że a + 1w żadnym wypadku nie jest on zdefiniowany, więc twój punkt dotyczy tylko tego, czy amoże być zerowy?
MM
Nie wydaje się, aby istniała jakakolwiek niezgodność co do zamierzonej semantyki, ani że obecna nazwa tej kategorii wartości wskaźnika jest nieodpowiednia dla tego scenariusza.
TC
@MM Myślę, że a + 1jest to niezdefiniowane i być może wynikowa wartość wskaźnika zostanie nazwana „wskaźnikiem za końcem”. Nie twierdzę, że odpowiedź jest zła. Jest to nieco nieprecyzyjne, ponieważ można to rozumieć jako długą dyskusję z konsensusem, że wystarczy jedynie sprecyzowanie, że wynikiem jest „wskaźnik za końcem”, aby rozwiązać problem. Problem z „wskaźnikiem za końcem” polega na tym, że jest on powyżej końca jakiegoś obiektu, a odjęcie 1od takiej wartości wskaźnika daje jeden wskaźnik do obiektu, co prawdopodobnie nie powinno mieć miejsca w przypadku tablic 0elementów.
Język Lawyer
2
@Bathsheba Czy uważasz, że w wadliwych sformułowaniach może być coś bardziej autorytatywnego?
Język Lawyer