Puntatori e riferimenti
Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 13 di 104.
Ora che hai capito la memoria stack e heap, esploriamo gli strumenti che ti permettono di lavorare direttamente con le posizioni di memoria: puntatori e riferimenti.
Un puntatore memorizza l'indirizzo di memoria di un'altra variabile. Lo dichiari con * e ottieni un indirizzo usando &.
int value = 42;
int* ptr = &value; // ptr contiene l'indirizzo di value
std::cout << ptr; // Stampa l'indirizzo di memoria
std::cout << *ptr; // Dereferenziazione: stampa 42Un riferimento è un alias per una variabile esistente. Una volta associato, si riferisce sempre a quella variabile. Lo dichiari con &.
int value = 42;
int& ref = value; // ref è un alias di value
ref = 100; // Modifica value portandolo a 100
std::cout << value; // Stampa 100Differenze principali:
| Puntatori | Riferimenti |
|---|---|
| Possono essere null | Devono essere inizializzati |
| Possono essere riassegnati | Non possono essere ricollegati |
Usa * per accedere al valore | Accedi direttamente al valore |
| Possono puntare a nulla | Sono sempre validi |
Entrambi sono essenziali per passare oggetti alle funzioni in modo efficiente senza copiarli e per lavorare con la memoria allocata nell'heap. I riferimenti sono più sicuri e semplici, mentre i puntatori offrono maggiore flessibilità quando devi riassegnarli o verificare che siano null.
Sfida
FacileCostruiamo un semplice sistema di manipolazione dei valori che mostra come puntatori e riferimenti funzionano in modo diverso quando si modificano i dati.
Creerai due file per organizzare il tuo codice:
ValueOps.h: definisci tre funzioni che modificano i valori interi in modi diversi:doubleByPointer(int* ptr): accetta un puntatore e raddoppia il valore a cui puntatripleByReference(int& ref): accetta un riferimento e triplica il valoreswapValues(int* a, int* b): accetta due puntatori e scambia i valori a cui puntano
main.cpp: leggi due interi dall'input, poi mostra sia i puntatori sia i riferimenti:- Stampa i valori originali:
"Original: <first> <second>" - Usa
doubleByPointersul primo valore, poi stampa:"After double: <first>" - Usa
tripleByReferencesul secondo valore, poi stampa:"After triple: <second>" - Usa
swapValuesper scambiare entrambi i valori, poi stampa:"After swap: <first> <second>"
- Stampa i valori originali:
Quando chiami funzioni con i puntatori, ricordati di usare l'operatore indirizzo (&) per passare l'indirizzo della variabile. I riferimenti funzionano in modo più naturale: passa direttamente la variabile.
Includi il tuo file header in main.cpp usando #include "ValueOps.h".
Provalo tu
#include <iostream>
#include "ValueOps.h"
using namespace std;
int main() {
// Lee dos números enteros de la entrada
int first, second;
cin >> first;
cin >> second;
// Imprime los valores originales
cout << "Original: " << first << " " << second << endl;
// TODO: Usa doubleByPointer con el primer valor (pasa su dirección usando &)
// TODO: Imprime después de duplicar
// TODO: Usa tripleByReference con el segundo valor (pasa la variable directamente)
// TODO: Imprime después de triplicar
// TODO: Usa swapValues para intercambiar ambos valores (pasa sus direcciones usando &)
// TODO: Imprime después del intercambio
return 0;
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniBuild e compilazione in C++File header e file sorgenteNamespace e ambitoIntroduzione alla programmazione orientata agli oggetti in C++Classi e oggetti a confrontoIl puntatore 'this'Metodi (funzioni membro)Attributi (membri dati)Fondamenti di costruttori e distruttoriRiepilogo - Calcolatrice semplice4Proprietà delle classi
Membri di istanza e staticiGetter e setterFunzioni membro constParola chiave mutableMetodi e variabili staticiFunzioni e classi friendRiepilogo - Gestore di conti bancari7Ereditarietà
Ereditarietà di baseLivelli di accesso nell’ereditarietàOrdine di chiamata di costruttori e distruttoriRidefinizione dei metodiFunzioni virtuali e VTableEreditarietà multiplaEreditarietà virtualeRiepilogo - Gerarchia dei dipendenti2Gestione della memoria
Memoria Stack vs HeapPuntatori e riferimentiMemoria dinamica (new/delete)Puntatori intelligenti in C++RAII in C++Riepilogo - Gestore di array dinamico5Incapsulamento
Specificatori di accesso in C++Specificatori di accesso in dettaglioOccultamento delle informazioniStruct vs classClassi annidate e interneRiepilogo - Sistema di registrazione degli studenti8Polimorfismo
Polimorfismo a compile time e a runtimeOverload delle funzioniFunzioni virtuali: ripassoFunzioni virtuali pureClassi astratteProgettazione delle interfacce in C++Dynamic casting e RTTIRipasso: calcolatrice di forme11Concetti avanzati di OOP
Composizione vs ereditarietàMixin tramite CRTPIdiom PimplType ErasureEnum class e tipizzazione forteGestione delle eccezioni in OOPGerarchie personalizzate di eccezioni14Pattern di progettazione - Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeRAII come pattern3Costruttori e distruttori
Costruttore predefinitoCostruttore con parametriCostruttore di copiaCostruttore di spostamentoListe di inizializzazione dei costruttoriCostruttori delegantiApprofondimento sui distruttoriRegola del Tre / Cinque / ZeroRipasso - classe String6Sovraccarico degli operatori
Introduzione al sovraccarico degli operatoriSovraccarico degli operatori aritmeticiSovraccarico degli operatori di confrontoOperatori di flussoSovraccarico dell'operatore di assegnazioneSovraccarico degli operatori [] e ()Operatori di conversione di tipoRipasso - Classe Matrix9Template
Template di funzioneTemplate di classeSpecializzazione dei templateTemplate variadiciBasi di SFINAE e dei trait di tipoRiepilogo - Contenitore genericoEsercitati da solo: Compilatore C++ online