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


10

Faccio spesso fatica a vedere i vantaggi dei puntatori (tranne per la programmazione di basso livello).

Perché usare char * invece di una stringa o char [] o quali vantaggi porta l'aritmetica del puntatore.

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


6
Questo sembrerà un po 'elitario, ma IMHO se devi chiedere informazioni su pro e contro dei puntatori, molto probabilmente non ne avrai bisogno.
Jas,

3
Probabilmente! Ma la domanda è ancora valida!
Zolomon,

1
Anche questo non è realmente indipendente dal linguaggio, in quanto non tutti i linguaggi di programmazione hanno veri e propri indicatori in senso C.
David Thornley,

Risposte:


6

I puntatori sono necessari per l'ubicazione dinamica della memoria, molte strutture di dati e la gestione efficiente di grandi quantità di dati. Senza puntatori, dovresti allocare tutti i dati del programma a livello globale o in funzioni o equivalenti e non avresti ricorso se la quantità di dati aumentasse oltre ciò che avevi inizialmente previsto. Esito a usare gli assoluti qui, ma per quanto ne so tutti i linguaggi per computer moderni hanno dei puntatori in un modo o nell'altro.

Nella maggior parte delle lingue che usano i puntatori, ci sono alcuni tipi di riferimenti che sono puntatori e forse alcuni tipi di riferimenti che non lo sono e non vi sono ulteriori differenze notazionali. Una conscella Lisp è una coppia di puntatori, sebbene a fixnumnon sia un puntatore. In Java, la variabile utilizzata per l'istanza di una classe è un puntatore, ma intnon lo è. La sintassi del linguaggio non riflette questo.

C è insolito in quanto i puntatori sono facoltativi, espliciti e consentono l'aritmetica esplicita dei puntatori. È perfettamente possibile scrivere struct foo bar; struct foo * baz;e, una volta allocata la memoria, bazè possibile utilizzare entrambi bare bazper rappresentare struct foos. Poiché i puntatori sono opzionali, è utile avere differenze notazionali. (È essenziale in C ++ per i puntatori intelligenti, come indicato boost::shared_ptr<foo> bar;, bar.reset()ha un significato ed bar->reset()è probabile che ne abbia uno molto diverso.)

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

Uno degli obiettivi di progettazione di C era scrivere Unix, e quindi doveva gestire le posizioni di memoria in modo dettagliato. (C è in realtà uno di una famiglia di linguaggi di implementazione del sistema comuni durante la progettazione, un altro esempio è Cybol per i computer Control Data. C è quello che è diventato un grande successo.) Pertanto, è possibile manipolare direttamente i puntatori C, assegnazione di indirizzi di memoria e calcolo di nuovi. Ciò ha anche portato ad alcune decisioni di progettazione in C. Le matrici si basano pesantemente sull'aritmetica del puntatore, e in effetti una matrice decade in un puntatore in moltissime situazioni. Il passaggio delle variabili alle funzioni C per riferimento avviene tramite puntatore. Non c'era un forte bisogno di matrici e variabili passanti per riferimento nella forma che avevano altre lingue contemporanee, quindi C non le ottenne.

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 o per fare cose di basso livello o per compiere cose di livello superiore per le quali non c'è una notazione speciale.


risposta molto bella
Kate Gregory,

1
Accetto questa risposta perché descrive al meglio la differenza che non potevo cogliere tra i puntatori in C / C ++ e Reference in Java.
OliverS,

Sarebbe utile aggiungere una breve spiegazione del motivo per cui Java non utilizza i puntatori per chiarire meglio il "con" percepito da Gosling (il principale creatore di Java).
Guido Anselmi,

10

Strutture dati complesse. Non è possibile creare qualcosa come un elenco collegato o un albero binario senza puntatori.

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


5
In Java, non ci sono puntatori. Tuttavia, è possibile creare un elenco di collegamenti e un albero binario. C'è una differenza tra riferimenti (come in Java) e puntatori (come in C).
StartClass0830,

7
Non c'è differenza tra riferimenti e puntatori. L'aritmetica del puntatore è specifica per C; ci sono altre lingue che hanno puntatori, ma non hanno l'aritmetica dei puntatori (ad es. Pascal).
zvrba,

1
Puntatori e riferimenti non sono sinonimi come pensi. Leggi questo per vedere le differenze. stackoverflow.com/questions/57483/...
StartClass0830

4
Per affrontare i primi due elementi di tale elenco: I riferimenti Java POSSONO essere riassegnati e POSSONO puntare a null. La caratteristica distintiva di un puntatore è che consente di fare riferimento indirettamente a un altro oggetto. La mia cartina di tornasole è: se puoi costruire una struttura di dati circolare (che puoi con riferimenti Java), è un puntatore. (Si noti che non è possibile creare una struttura di dati circolare con riferimenti C ++.)
zvrba,

1
C'è una differenza tra puntatori e riferimenti. C #, per esempio, ha entrambi . ( blogs.msdn.com/b/ericlippert/archive/2009/02/17/… )
Steven Evers

2
  • Con i puntatori è possibile allocare e deallocare la memoria in fase di esecuzione.
  • Inoltre, è possibile utilizzare strutture dati di grandi dimensioni al di fuori dell'ambito consentito senza essere copiate.

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


1
I riferimenti in C ++ NON sono puntatori sicuri. I riferimenti in C ++ non hanno nulla a che fare con i puntatori. I riferimenti in C ++ sono alias . Non possono essere assegnati NULLe non possono essere modificati dopo la loro creazione.
Billy ONeal

@Billy: i riferimenti C ++ sono di solito implementati usando i puntatori e funzionano in modo simile in alcune cose, quindi le persone continuano a pensarli come una sorta di puntatore vincolato.
David Thornley,

2

Praticamente qualsiasi programma per computer ha bisogno di ispezionare e modificare i valori nella memoria (noto come sbirciare e colpire, a quelli di noi che sono abbastanza grandi). Devi 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 rappresenti una posizione in memoria. Anche se l'ambiente di programmazione lo nasconde sotto un'astrazione, è ancora lì.


2

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

  • ambito più ampio di una singola funzione: alloca l'oggetto sull'heap e passa il puntatore a lungo
  • la funzione più veloce richiede oggetti di grandi dimensioni poiché non si ha il costo di copia del valore pass-by
  • un modo per abilitare una funzione per modificare i parametri passati ad essa
  • risparmiare 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 li hanno effettivamente solo. I tipi di riferimento in C # e Java sono essenzialmente puntatori mascherati da oggetti solidi.

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


1

I puntatori possono essere più veloci e possono comportare un minor sovraccarico, sia nelle strutture di dati che nel ridurre il footprint dell'esecuzione del programma. (Nota la parola "can".)

In generale la regola è, se hai allocato una risorsa, eseguendo la tua allocazione o facendo fare qualcosa per tuo conto, allora è tuo compito rilasciarla al termine.

L'onere di fare quanto sopra è rimettere la responsabilità sullo sviluppatore, piuttosto che farlo eseguire dal runtime. Ciò ha alcuni più vantaggi in quanto le cose possono essere vissute più a lungo, oltrepassare i confini, o essere smaltite in momenti più opportuni, o non dover trasportare il peso di un bidone della spazzatura.

In casi esotici, che di solito comportano eccezioni e portata, ci sono alcuni casi limite che richiedono di essere un po 'più attenti se si evita il codice che esegue la pulizia. 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 l'indirizzamento indiretto.

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

La contro è di solito uno spreco dimenticando di rilasciare qualcosa, o rilasciandolo più di una volta, o facendo riferimento a qualcosa dopo che è stato rilasciato, o facendo riferimento a qualcosa quando non si punta da nessuna parte. Queste cose spesso provocano crash 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'utilizzo dei puntatori non dovrebbe essere più problematico di qualsiasi altra struttura di dati. Ancora una volta, non è scienza missilistica e la gente lo ha fatto per decenni senza nemmeno batter ciglio. In questi giorni viene semplicemente insegnato in modo meno approfondito.

Detto questo, a meno che tu non abbia bisogno di puntatori, la convinenza e i casi esoitici forniti da una buona raccolta dei rifiuti rendono il lavoro in un ambiente gestito molto più piacevole. È 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 programmatore, in cambio di un runtime che fa un po' di sollevamento extra.


0

La risposta migliore è effettivamente 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 un linguaggio di livello superiore.


-1

I puntatori forniscono una visibilità sulla macchina necessaria per la programmazione più interessante. La maggior parte delle lingue moderne ti nasconde semplicemente i pezzi grintosi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.