2013-05-20 23 views
15

This earlier question pyta, co oznacza this[0] w języku C#. W C++, this[0] oznacza "zerowy element tablicy wskazywany przez this."Czy to [0] jest bezpieczne w C++?

Czy to gwarantuje, że nie spowoduje niezdefiniowanego zachowania w C++, aby odwołać się do obiektu odbiornika w ten sposób? Nie jestem zwolennikiem korzystania z tej składni i jestem w większości ciekawy, czy specyfikacja gwarantuje, że to zawsze zadziała.

Dzięki!

+1

Jestem prawie pewny, że jest dobrze zdefiniowany, idąc wzdłuż linii jak '& obj + 1'. – chris

+3

Używałem tego czasami z gdb: mówisz, że zrobiłeś 'p-wyrażenie-złożone-to-yield-wskazy'', ale chciałeś zobaczyć zawartość obiektu, a nie wskaźnika, więc naciśnij w górę, wpisz' [0] 'i gotowe. Nie trzeba przewijać do początku wyrażenia i dodawać nawiasów (prawdopodobnie). – rodrigo

Odpowiedz

19

Dla każdego ważnego wskaźnika obiektu p, p[0] jest równoważna *p. Tak więc this[0] jest odpowiednikiem *this. Nie ma w tym nic więcej. Podobnie jak możesz usunąć dowolny poprawny wskaźnik za pomocą [0], możesz usunąć z nim dereferencję this.

Innymi słowy, jest to po prostu "podstępny" sposób napisania *this. Może służyć do zaciemniania kodu. Prawdopodobnie może być również użyty w pewnych szczególnych okolicznościach do użytecznych celów, ponieważ każdy samodzielny obiekt może być traktowany jako tablica o rozmiarze 1. (Od C++ 03, Operatory dodawania: "Dla celów tych operatorów, wskaźnik do obiektu bezbarwnego zachowuje się tak samo jak wskaźnik do pierwszego elementu tablicy o długości jeden z typem obiektu jako typem elementu. ")

PS Jak zauważył Johannes w komentarzach, przy użyciu funkcji C++ 11 można wymyślić kontekst, w którym this jest wskaźnikiem do niekompletnego typu. W takim przypadku wyrażenie this[0] staje się nieważne, podczas gdy wyrażenie *this pozostaje poprawne.

+5

Jestem prawie pewien, że jesteś tego świadomy, ale odpowiedź stwierdza, że ​​jest inaczej. Następujące jest źle sformułowane, a zastąpienie 'this [0]' przez '* this' sprawia, że ​​jest dobrze sformatowany. 'struct A {auto f() -> decltype (to [0]); }; '. –

+2

Dobrze, co powiedział Johannes, 'p [0]' nie działa, gdy 'p' jest wskaźnikiem typu niekompletnego. Aby dodać do tego, typ może być niekompletny, ponieważ nie jest jeszcze zakończony, jak w przykładzie Johannesa, ale może to być również spowodowane tym, że typ nie może być ukończony (np. 'T (*) []'). To (oczywiście) również nie działa dla typów wskaźników nieobiektowych. – hvd

11

this[0] jest taki sam jak *(this + 0), więc rzeczywiście jest w porządku (choć trochę dziwne).

+2

Przepraszamy za bycie pedantycznym, ale czy to gwarantuje specyfikacja ISO? Doskonale zdaję sobie sprawę z tej tożsamości, ale specyfikacja często rozróżnia obiekty i tablice. – templatetypedef

+0

@templatetypedef, '& obj + 1' jest ważne, mimo że' obj' jest tablicą lub pojedynczym obiektem. Zakładam, że to samo dotyczy tutaj. – chris

+3

@templatetypedef: W rzeczywistości '[]' nie działa na tablicach, tylko na wskaźnikach. Tablica rozpada się na wskaźnik, a '[]' działa ze wskaźnikiem i indeksem. Tak, tak, jest to gwarantowane. – rodrigo

0

Jest to odpowiednik (z definicji) do *(this + 0), który jest taki sam jak *this. Jest bezpieczny i dobrze zdefiniowany, ale dziwny.

1

AFAIK zasadzie this[0] jest dokładnie taka sama jak *this, jak this jest po prostu normalny wskaźnik. Tak, więc można go bezpiecznie używać.

array[1] byłaby taka sama jak *(array + 1) (gdy array jest ważna) FYI ...

-2

this[0] jest taka sama jak *(this + sizeof(this)*0) więc jest to dość bezpieczne

Dodano mały sprawdzian jako odpowiedź na komentarz

struct A 
{ 
    void * _a; 
    int _b; 

    A * getThis(int index) 
    { 
     return &(this[index]); 
    } 
}; 

int main(int argc, char * argv[]) 
{ 
    A mas[100]; 

    std::cout << ((long long) mas[0].getThis(50) == (long long) &(mas[50])) << std::endl; 
    return 0; 
} 
+7

Podczas gdy twoja odpowiedź jest * technicznie * poprawna. 'Sizeof (this)' jest zbędne i sugeruje, że 'ten [1]' jest taki sam jak '* (this + sizeof (this) * 1)'. Albo że "to [N]" jest zwykle równoważne '* (this + sizeof (this) * N)'. Jest to oczywiście nieprawdziwe. –

+0

@BenjaminLindley zobaczyć mały test, który, jak sądzę, udowodnić mój punkt –

+3

Nie wiem, co punkt próbujesz udowodnić swoim testem. Czy rozumiesz mój komentarz? Chodzi mi o to, że 'to [N]' jest * nie * równoważne '* (this + sizeof (this) * N)', ale twoja pierwotna odpowiedź, moim zdaniem, implikuje, że są one równoważne. 'Sizeof (this)' jest całkowicie bezcelowe i tylko się sprawdza, ponieważ jest pomnożone przez 0. Ale dla każdej innej wartości 'N' oprócz 0, to nie działa. Dlaczego jest to w twojej formule? –

Powiązane problemy