2010-01-27 27 views
8

Sono uno studente di programmazione con due classi in C#, ma sto solo prendendo la mia prima lezione in C++, e quindi sono esposto a dei suggerimenti.Usi comuni per i puntatori?

So come funzionano e il modo corretto di usarli, ma mi sono chiesto alcuni dei modi in cui i programmatori professionisti utilizzano i puntatori nei loro programmi.

Quindi, come si usano i puntatori? O tu?

Questo mi aiuterà a capire alcune applicazioni pratiche per i puntatori, quindi grazie!

+0

Guardate questo per capire perché i puntatori sono a volte utilizzati per i parametri: http://stackoverflow.com/questions/2139224/2139254#2139254 – sbi

risposta

16

Ogni volta che si utilizza un riferimento in C#. Un "riferimento" è solo un puntatore con eleganti airbag di sicurezza attorno ad esso.

Uso i puntatori circa una volta ogni sei righe nel codice C++ che scrivo. In cima alla mia testa, questi sono gli usi più comuni:

  • Quando ho bisogno di creare dinamicamente un oggetto la cui durata supera l'ambito in cui è stato creato.
  • Quando ho bisogno di allocare un oggetto le cui dimensioni sono sconosciute in fase di compilazione.
  • Quando devo trasferire la proprietà di un oggetto da una cosa all'altra senza effettivamente copiarlo (come in una lista collegata/heap/qualunque di strutture veramente grandi e costose)
  • Quando devo fare riferimento allo stesso oggetto da due posti diversi.
  • Quando ho bisogno di affettare una matrice senza copiarla.
  • Quando ho bisogno di scrivere direttamente in una regione specifica della memoria (perché ha un IO mappato in memoria).
+1

"Quando devo fare riferimento allo stesso oggetto da due posti diversi". Per quello, un riferimento è spesso migliore. – sbi

+0

Non è possibile riposizionare un riferimento. Intendevo i casi in cui ho oggetti A, B, X e Y, tutti in ambiti diversi. X e Y hanno entrambi bisogno di riferirsi ad A. In seguito, senza creare una nuova X e Y, devo fare in modo che entrambi si riferiscano a B. Se X e Y contengono entrambi un 'Foo & A', allora non posso ripeterlo a B. Potrei avere una sorta di classe di handle di fantasia che ha una funzione .Reseat(), ma internamente userebbe comunque un puntatore. – Crashworks

+0

"Non è possibile riposizionare un riferimento." Certo che non puoi. Ma questo non è necessario ogni volta che è necessario fare riferimento allo stesso oggetto da due luoghi diversi. (Vedi i parametri della funzione, per esempio.) – sbi

1

Se hai un po 'di tempo a disposizione per leggere un libro, ti consiglio di leggere The C Programming Language che fa un uso pesante dei puntatori.

Un semplice esempio di una funzione standard:

/* strlen: return length of string s */ 
int strlen(char *s) { 
    char *p = s; 
    while (*p != '\0') p++; 
    return p - s; 
} 
+2

E perché qualcuno dovrebbe usare che in reale ** ** C++ di codice (tranne quando scrivere una stringa di classe)? –

+0

Potrebbe essere necessario calcolare la lunghezza di una stringa. – Crashworks

+5

Lasciatemi riformulare la frase: per favore non raccomandare * C Programming Language * e C-style per chi avvia un corso in C++. –

6

Per staters, di utilizzarli nel vostro data structures, come lista collegata, ecc ovunque avete bisogno in modo dinamico la memoria allocata, cioè la memoria che don' Sappiamo le dimensioni di in fase di compilazione, userete un pointer.

1

parte 1 di 2

puntatori sono spesso richiesto di interfacciarsi con librerie C quando i dati deve essere trasmesso in un'API esistente. Questo meccanismo non è limitato ai sistemi "legacy", gli esempi moderni includono OpenGL, DirectX e Win32.

sotto è un esempio OpenGL: glVertexPointer (int, float, int, float *) richiede un puntatore galleggiante come primo argomento.

GLfloat vertices[] = {...}; // 24 of vertex coords 
... 
// activate and specify pointer to vertex array 
glEnableClientState(GL_VERTEX_ARRAY); 
glVertexPointer(3, GL_FLOAT, 0, vertices); 

// draw a cube 
glDrawArrays(GL_QUADS, 0, 24); 

// deactivate vertex arrays after drawing 
glDisableClientState(GL_VERTEX_ARRAY); 

invece di utilizzare una matrice definita staticamente sarebbe ok per effettuare le seguenti operazioni:

Glfloat *vertex = new GlFloat[24]; 
... 
glVertexPointer(3, GL_FLOAT, 0, vertices); 
... 
delete [] vertex. 

o se si desidera utilizzare std :: vector

std::vector<Glfloat> vertex; 
vertex.resize(24); 
... 
glVertexPointer(3, GL_FLOAT, 0, &vertices[0]); 
... 

Parte 2 di 2

I puntatori agli oggetti e ai puntatori di funzione sono utili per definire la funzione membro statico che deve operare su un'istanza specifica di una classe. Questo idioma appare nei meccanismi di callback.

class foo { 
    ... 
    public: 
    static int s_callback0(void* obj){ 
     return (foo*)(obj)->callback0(); 
    } 
    int callback0(){ 
     ... 
    } 
    ... 
}; 

class callbackAPI { 
    public: 
    int setCallback(int(*fn)(void*),void* context){ 
     m_fn(fn); 
     m_context(context); 
    } 
    void run(){ 
     m_fn(m_context); 
    } 
    private: 
    int(*m_fn)(void*); 
    void *m_context; 
}; 

main { 
    foo f; 
    callbackAPI cb; 
    cb.setCallback(foo::s_callback0,f); 
    cb.run(); 
} 

Se si ha il controllo di callbackAPI risultati simili potrebbero essere ottenuti con l'ereditarietà e modelli. Gli esempi sopra illustrano un modo di lavorare con un callbackAPI fornito da una terza parte quando richiesto per fornire un puntatore a funzione.