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?


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.


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 .


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.