Contenitori STL
Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 71 di 104.
I contenitori STL sono classi template che memorizzano e organizzano raccolte di oggetti. Ogni tipo di contenitore è ottimizzato per diversi schemi di accesso e operazioni. Scegliere il contenitore giusto per le tue esigenze può influire significativamente sulle prestazioni del tuo programma.
I contenitori sequenziali mantengono gli elementi in un ordine specifico:
#include <vector>
#include <list>
std::vector<int> vec = {1, 2, 3}; // Array dinamico, accesso casuale rapido
vec.push_back(4); // Aggiunta in fondo: O(1) ammortizzato
int x = vec[2]; // Accesso per indice: O(1)
std::list<int> lst = {1, 2, 3}; // Lista doppiamente concatenata
lst.push_front(0); // Aggiunta all'inizio: O(1)
lst.push_back(4); // Aggiunta in fondo: O(1)I contenitori associativi memorizzano gli elementi in ordine ordinato per consentire ricerche rapide:
#include <map>
#include <set>
std::set<int> s = {3, 1, 4, 1}; // Elementi unici ordinati: {1, 3, 4}
s.insert(2); // Inserimento: O(log n)
bool found = s.count(3); // Verifica dell'esistenza: O(log n)
std::map<std::string, int> ages; // Coppie chiave-valore, ordinate per chiave
ages["Alice"] = 25; // Inserimento/aggiornamento: O(log n)
ages["Bob"] = 30;
std::cout << ages["Alice"]; // Accesso: O(log n)I contenitori non ordinati usano tabelle hash per una ricerca media ancora più veloce:
#include <unordered_map>
std::unordered_map<std::string, int> scores;
scores["player1"] = 100; // Inserimento: O(1) in media
scores["player2"] = 200;
std::cout << scores["player1"]; // Accesso: O(1) in mediaUsa vector quando ti serve un accesso casuale rapido, list per inserimenti frequenti nel mezzo, map/set quando ti servono dati ordinati e unordered_map quando la velocità di ricerca è fondamentale e l’ordine non è importante.
Sfida
FacileCostruiamo un sistema di gestione dei voti degli studenti che mostri come i diversi contenitori STL siano adatti a scopi diversi. Userai più tipi di contenitori per organizzare in modo efficiente i dati degli studenti, scegliendo il contenitore giusto per ogni attività.
Creerai due file per organizzare il codice:
GradeManager.h: definisci una classeGradeManagerche usa più contenitori STL per gestire le informazioni sugli studenti.La tua classe dovrebbe usare:
- Un
std::vector<std::string>per memorizzare i nomi degli studenti nell'ordine in cui sono stati aggiunti - Un
std::map<std::string, int>per associare ogni nome di studente al relativo voto - Un
std::set<int>per tenere traccia di tutti i voti unici assegnati
Implementa questi metodi:
addStudent(const std::string& name, int grade): aggiunge uno studente con il relativo voto a tutti e tre i contenitorigetGrade(const std::string& name): restituisce il voto di uno studente specificato usando la mappaprintRoster(): stampa tutti i nomi degli studenti nell'ordine in cui sono stati aggiunti (dal vettore), ciascuno su una nuova rigaprintGrades(): stampa tutti gli studenti con i relativi voti in ordine alfabetico (la mappa lo gestisce automaticamente), nel formatoname: gradesu ogni rigaprintUniqueGrades(): stampa tutti i voti unici in ordine crescente (se ne occupa l'insieme), separati da spazi e seguiti da un carattere di nuova riga
- Un
main.cpp: leggi gli input e mostra come ogni tipo di contenitore sia adatto a uno scopo diverso.Leggi sei input (ciascuno su una riga separata):
- Nome del primo studente
- Voto del primo studente (intero)
- Nome del secondo studente
- Voto del secondo studente (intero)
- Nome del terzo studente
- Voto del terzo studente (intero)
Crea un
GradeManagere aggiungi tutti e tre gli studenti. Poi mostra i diversi comportamenti dei contenitori:- Stampa
Roster (insertion order):, poi chiamaprintRoster() - Stampa
Grades (alphabetical):, poi chiamaprintGrades() - Stampa
Unique grades:, poi chiamaprintUniqueGrades() - Cerca il voto del secondo studente e stampa
<name>'s grade: <grade>
Per esempio, con gli input Charlie, 85, Alice, 90, Bob, 85:
Roster (insertion order):
Charlie
Alice
Bob
Grades (alphabetical):
Alice: 90
Bob: 85
Charlie: 85
Unique grades:
85 90
Alice's grade: 90Nota come il vettore mantenga l'ordine di inserimento (Charlie, Alice, Bob), la mappa ordini automaticamente le chiavi (Alice, Bob, Charlie) e l'insieme memorizzi solo i valori unici in ordine crescente (85 compare una sola volta, non due). Ogni tipo di contenitore è ideale per attività diverse!
Provalo tu
#include <iostream>
#include <string>
#include "GradeManager.h"
using namespace std;
int main() {
// Leggi i dati di input per tre studenti
string name1, name2, name3;
int grade1, grade2, grade3;
cin >> name1;
cin >> grade1;
cin >> name2;
cin >> grade2;
cin >> name3;
cin >> grade3;
// TODO: Crea un oggetto GradeManager
// TODO: Aggiungi tutti e tre gli studenti a GradeManager
// TODO: Stampa "Roster (insertion order):" e chiama printRoster()
// TODO: Stampa "Grades (alphabetical):" e chiama printGrades()
// TODO: Stampa "Unique grades:" e chiama printUniqueGrades()
// TODO: Cerca il voto del secondo studente e stampa "<name>'s grade: <grade>"
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 dipendenti10Panoramica della STL
Panoramica e filosofia della STLContenitori STLIteratoriAlgoritmi STLFuntori ed espressioni lambdaRiepilogo - Frequenza delle parole2Gestione 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