2013-05-20 7 views
15

This earlier question chiede cosa significa this[0] in C#. In C++, this[0] significa "l'elemento zeroth dell'array puntato da this".Questo è [0] sicuro in C++?

È garantito che non causa un comportamento indefinito in C++ per fare riferimento all'oggetto destinatario in questo modo? Non sto sostenendo l'utilizzo di questa sintassi, e sono per lo più curioso di sapere se la specifica garantisce che funzionerà sempre.

Grazie!

+1

Sono abbastanza sicuro che sia ben definito, seguendo le linee di come '& obj + 1' è. – chris

+3

L'ho usato qualche volta con gdb: diciamo che hai fatto p espressione-complesso-che-yield-pointer', ma volevi vedere il contenuto dell'oggetto, non il puntatore, quindi premi su, scrivi '[0] 'e fatto. Non c'è bisogno di scorrere fino all'inizio dell'espressione e aggiungere parentesi (probabilmente). – rodrigo

risposta

19

Per qualsiasi puntatore di oggetto valido p, p[0] equivale a *p. Quindi this[0] equivale a *this. Non c'è nient'altro. Proprio come è possibile annullare il riferimento a qualsiasi puntatore valido utilizzando [0], è possibile annullare il riferimento a this.

In altre parole, è solo un modo "difficile" per scrivere *this. Può essere usato per offuscare il codice. Può essere probabilmente usato in alcune circostanze specifiche anche per scopi utili, dal momento che qualsiasi oggetto autonomo può essere pensato come una matrice di dimensione 1. (Da C++ 03, Operatori additivi: "Ai fini di questi operatori, un puntatore a un oggetto nonarray si comporta come un puntatore al primo elemento di una matrice di lunghezza uno con il tipo dell'oggetto come tipo di elemento. ")

PS Come ha osservato Johannes nei commenti, utilizzando le funzionalità di C++ 11 è possibile creare un contesto in cui this è un puntatore a un tipo incompleto. In tal caso, l'espressione this[0] non è più valida, mentre l'espressione *this rimane valida.

+5

Sono sicuro che ne sei a conoscenza, ma la risposta lo dice diverso. Quanto segue non è corretto e sostituendo 'this [0]' con '* this' lo rende ben fatto. 'struct A {auto f() -> decltype (questo [0]); }; '. –

+2

Esatto, ciò che Johannes ha detto, 'p [0]' non funziona quando 'p' è un puntatore a un tipo incompleto. Per aggiungere a ciò, il tipo potrebbe essere incompleto perché non è stato ancora completato, come nell'esempio di Johannes, ma potrebbe anche essere dovuto al fatto che il tipo non può essere completato (come ad esempio 'T (*) []'). Ovviamente non funziona anche con i tipi di puntatori non oggetto. – hvd

11

this[0] è lo stesso di *(this + 0), quindi effettivamente questo va bene (anche se un po 'strano).

+2

Ci scusiamo per essere pedanti, ma le specifiche ISO lo garantiscono? Sono ben consapevole di questa identità, ma le specifiche spesso fanno una distinzione tra oggetti e matrici. – templatetypedef

+0

@templatetypedef, '& obj + 1' è valido nonostante' obj' sia un array o un singolo oggetto. Assumerei lo stesso vale qui. – chris

+3

@templatetypedef: In realtà, '[]' non funziona sugli array, solo sui puntatori. L'array decade in un puntatore e '[]' funziona con il puntatore e l'indice. Quindi, sì, è garantito. – rodrigo

0

È equivalente (per definizione) a *(this + 0), che è lo stesso di *this. È sicuro e ben definito, ma strano.

3

Sì, è la stessa cosa di *this

1

per quanto ne so praticamente this[0] è esattamente la stessa di *this, come this è solo un normale puntatore. Quindi sì, è sicuro da usare.

array[1] sarebbe lo stesso di *(array + 1) (quando array è valido) fyi ...

-2

this[0] è uguale a *(this + sizeof(this)*0) quindi è abbastanza sicuro

Aggiunto piccolo test in risposta al commento

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

Mentre la tua risposta è * tecnicamente * corretta. La 'sizeof (this)' è superflua e implica che 'this [1]' è la stessa cosa di '* (this + sizeof (this) * 1)'. O che 'questo [N]' è generalmente equivalente a '* (questo + sizeof (questo) * N)'. Questo è, naturalmente, falso. –

+0

@BenjaminLindley vedere un piccolo test che, penso, dimostri il mio punto –

+3

Non so che cosa stai cercando di dimostrare con il tuo test. Hai capito il mio commento? Il mio punto è che "questo [N]' è * non * equivalente a '* (questo + sizeof (questo) * N)', ma la tua risposta originale, a mio avviso, implica che siano equivalenti. La 'sizeof (this)' è completamente inutile, e capita solo di funzionare perché viene moltiplicata per 0. Ma per qualsiasi altro valore di 'N' oltre a 0, non funziona. Allora, perché è nella tua formula? Il puntatore –