Quali sono i casi d'uso e i vantaggi dei puntatori? [chiuso]

10

Spesso faccio fatica a vedere i vantaggi dei puntatori (tranne che per la programmazione di basso livello).

Perché usare char * invece di String o char [] o quali vantaggi offre l'aritmetica del puntatore.

Quindi quali sono i pro e i casi d'uso dei puntatori?

    
posta OliverS 02.11.2010 - 10:24
fonte

8 risposte

6

I puntatori sono necessari per la posizione dinamica della memoria, molte strutture dati e una gestione efficiente di grandi quantità di dati. Senza i puntatori, dovresti allocare tutti i dati del programma a livello globale o in funzioni o equivalenti, e non avresti alcun ricorso se la quantità di dati crescesse oltre ciò che avevi inizialmente previsto. Ho esitato a usare assoluti qui, ma per quanto ne so tutti i linguaggi informatici moderni hanno dei puntatori in una forma o nell'altra.

Nella maggior parte delle lingue che usano i puntatori, ci sono alcuni tipi di riferimenti che sono puntatori e forse certi tipi di riferimenti che non lo sono, e non c'è altra differenza notazionale. Una cella Lisp cons è una coppia di puntatori, sebbene fixnum non sia un puntatore. In Java, la variabile utilizzata per l'istanza di una classe è un puntatore, ma un int non lo è. La sintassi del linguaggio non riflette questo.

C è inusuale in quanto i puntatori sono opzionali, espliciti e consentono l'aritmetica del puntatore esplicita. È perfettamente possibile scrivere struct foo bar; struct foo * baz; e, una volta allocata memoria per baz , puoi utilizzare sia bar che baz per rappresentare struct foo s. Poiché i puntatori sono facoltativi, è utile avere differenze notazionali. (È essenziale in C ++ per i puntatori intelligenti, dato come boost::shared_ptr<foo> bar; , bar.reset() ha un significato e bar->reset() probabilmente ne ha uno molto diverso.)

(In realtà, i puntatori espliciti erano spesso usati in altri linguaggi quando C era originariamente sviluppato, come ^ in Pascal. C è una lingua più vecchia della maggior parte in uso comune oggi, e mostra.)

Uno degli obiettivi di progettazione di C era scrivere in Unix e quindi era necessario gestire le posizioni di memoria in modo dettagliato. (C è in realtà una delle famiglie di linguaggi di implementazione del sistema comuni durante la progettazione, un altro esempio è Cybol per i computer di Control Data. C è quello che è diventato un grande successo.) Pertanto, è possibile manipolare direttamente i puntatori C, assegnare indirizzi di memoria e calcolarne di nuovi. Ciò ha portato anche ad alcune decisioni di progettazione in C. Gli array C sono basati pesantemente sull'aritmetica dei puntatori, e in effetti un array decade in un puntatore in moltissime situazioni. Il passaggio delle variabili alle funzioni C mediante riferimento avviene tramite puntatore. Non c'era un strong bisogno di array e di variabili di passaggio per riferimento nella forma che avevano altri linguaggi contemporanei, quindi C non li ha ottenuti.

Quindi, la risposta è che, nella maggior parte delle lingue al giorno d'oggi, si usano costantemente i puntatori senza essere ricordati del fatto. In C, e in misura minore in C ++, usi i puntatori per fare cose di basso livello, o come realizzare cose di livello superiore per cui non esiste una notazione speciale.

    
risposta data 02.11.2010 - 15:26
fonte
10

Strutture dati complesse. Non puoi creare qualcosa come una lista collegata o un albero binario senza puntatori.

Non ci sono "pro" e "contro" di puntatori. Sono solo uno strumento, come un martello.

    
risposta data 02.11.2010 - 10:30
fonte
2
  • Con i puntatori è possibile allocare e deallocare la memoria in runtime.
  • Ed è possibile utilizzare strutture di dati di grandi dimensioni al di fuori dell'ambito consentito senza essere copiate.

I riferimenti in C ++, Java e altri tipi di linguaggi sono solo dei "puntatori sicuri". E questi riferimenti sono usati molto in Java.

    
risposta data 02.11.2010 - 11:05
fonte
2

char* è un esempio scadente di puntatori. Probabilmente stai meglio usando std::string (o qualche altro tipo migliore che gestisce la tua unicode / ansi / multibyte specialness) rispetto a char* . Per quasi ogni altro esempio di puntatori ( Employee* , PurchaseOrder* , ...), tuttavia, ci sono molti vantaggi:

  • scope più grande di una singola funzione - alloca l'oggetto sull'heap e passa il puntatore per un lungo periodo
  • chiamate di funzione più veloci per oggetti di grandi dimensioni poiché non si ha il costo di copia del valore per passata
  • un modo per consentire a una funzione di modificare i parametri passati ad essa
  • salva spazio e tempo nelle raccolte copiando solo un indirizzo anziché un intero oggetto

In effetti, i puntatori sono così importanti che la maggior parte delle lingue che sembrano non averli in realtà ne hanno solo. I tipi di riferimento in C # e Java sono essenzialmente dei puntatori mascherati da oggetti solidi.

Ora, la manipolazione del puntatore ( p++ su un puntatore o p += delta ) è tutta una storia diversa. Alcune persone pensano che sia pericoloso, alcune persone pensano che sia fantastico. Ma questo è ancora più lontano dalla tua domanda.

    
risposta data 02.11.2010 - 13:39
fonte
1

Praticamente qualsiasi programma per computer ha bisogno di ispezionare e modificare i valori in memoria (noti come sbirciare e colpire, per quelli di noi che sono abbastanza grandi). È necessario controllare dove sono in memoria quei valori, in modo che il risultato sia prevedibile (e in alcuni casi, l'ordine è importante: il caricamento del codice eseguibile è un esempio). Pertanto è necessario disporre di un tipo di dati che rappresenta una posizione in memoria. Anche se il tuo ambiente di programmazione nasconde quello sotto un'astrazione, è ancora lì.

    
risposta data 02.11.2010 - 11:13
fonte
1

I puntatori possono essere più veloci e possono sostenere un sovraccarico minore, sia nelle strutture dati sia nel mantenere basso il footprint di esecuzione del programma. (Si prega di notare la parola "può".)

In generale, la regola è che, se hai assegnato una risorsa, eseguendo la tua allocazione o facendola fare qualcosa per tuo conto, allora il tuo compito è di rilasciarlo una volta terminato.

L'onere di fare quanto sopra è ricollocare la responsabilità sullo sviluppatore, piuttosto che fare eseguire il runtime. Ciò ha alcuni più vantaggi in quanto le cose possono essere vissute più a lungo, o attraversare i confini, o essere smaltite in tempi più opportuni, o non devono portare il peso di un garbage collector.

In casi esotici, che di solito coinvolgono eccezioni e portata, ci sono alcuni casi limite che richiedono di essere un po 'più cauti se il codice che fa la pulizia viene evitato. Realisticamente, questi casi possono essere progettati intorno. Abbiamo vissuto senza codice gestito per molti decenni.

Spesso ciò che rende i puntatori "difficili" è semplicemente non capire cosa sta succedendo a livello hardware. Non è altro che indiretta.

I puntatori ti danno un accesso molto più grezzo, e questo può essere molto utile, intelligente o necessario. Puoi indicare ovunque e trattarlo praticamente come qualsiasi cosa. Se usi bene i tuoi poteri simili a quelli di Dio, è molto, molto buono.

Il lato negativo è di solito uno spreco, dimenticando di rilasciare qualcosa, o rilasciandolo più di una volta, o riferendosi a qualcosa dopo che è stato rilasciato, o riconfigurando qualcosa quando non stai puntando da nessuna parte. Queste cose spesso si traducono in arresti anomali spettacolari e, ad essere onesti, di solito indicano che hai un problema logico, piuttosto che i puntatori sono fragili.

Se sei uno sviluppatore solido, l'uso dei puntatori non dovrebbe essere più problematico di qualsiasi altra struttura di dati. Di nuovo, non è scienza missilistica, e la gente lo ha fatto per decenni senza nemmeno battere ciglio. Al giorno d'oggi è appena insegnato molto meno.

Tutto ciò detto, a meno che tu non abbia bisogno di indicazioni, i casi di convinzione e di denuncia che una buona raccolta di dati inutili fornisce rende il lavoro in un ambiente gestito molto più bello. È bello essere in grado di afferrare un po 'di memoria, usarlo e abbandonarlo, sapendo che in un secondo momento potrebbe essere scartato, se ha senso farlo. Questo è un po 'meno codice da parte del codificatore, in cambio di un runtime che fa un po' di sollevamento extra.

    
risposta data 02.11.2010 - 16:21
fonte
0

La risposta migliore è in realtà inclusa nella domanda: i puntatori sono per la programmazione di basso livello. Certo, se stai usando C, non usare i puntatori è come programmare con una mano legata dietro la schiena, ma la risposta è usare invece un linguaggio di livello superiore.

    
risposta data 02.11.2010 - 13:42
fonte
-1

I puntatori forniscono una visibilità sulla macchina necessaria per la programmazione più interessante. La maggior parte dei linguaggi moderni nasconde semplicemente i pezzi grintosi da te.

    
risposta data 02.11.2010 - 16:45
fonte

Leggi altre domande sui tag