summaryrefslogtreecommitdiffhomepage
path: root/it-it
diff options
context:
space:
mode:
Diffstat (limited to 'it-it')
-rw-r--r--it-it/c++-it.html.markdown283
1 files changed, 270 insertions, 13 deletions
diff --git a/it-it/c++-it.html.markdown b/it-it/c++-it.html.markdown
index 92ebc165..4af30176 100644
--- a/it-it/c++-it.html.markdown
+++ b/it-it/c++-it.html.markdown
@@ -8,6 +8,7 @@ contributors:
- ["Connor Waters", "http://github.com/connorwaters"]
translators:
- ["Robert Margelli", "http://github.com/sinkswim/"]
+ - ["Tommaso Pifferi", "http://github.com/neslinesli93/"]
lang: it-it
---
@@ -151,7 +152,7 @@ namespace Primo {
namespace Secondo {
void foo()
{
- printf("Questa è Secondo::foo\n")
+ printf("Questa è Secondo::foo\n");
}
}
@@ -805,6 +806,94 @@ void faiQualcosaConUnFile(const std::string& nomefile)
// sono tutti automaticamente distrutti con i loro contenuti quando escono dalla visibilità.
// - I mutex usano lock_guard e unique_lock
+// I contenitori che utilizzano chiavi non-primitive (classi personalizzate)
+// richiedono la funzione di confronto nell'oggetto stesso, o tramite un puntatore a funzione.
+// Le chiavi primitive hanno funzioni di confronto già definite, ma puoi sovrascriverle.
+class Foo {
+public:
+ int j;
+ Foo(int a) : j(a) {}
+};
+struct funzioneDiConfronto {
+ bool operator()(const Foo& a, const Foo& b) const {
+ return a.j < b.j;
+ }
+};
+// Questo non è permesso, anche se qualche compilatore potrebbe non dare problemi
+//std::map<Foo, int> fooMap;
+std::map<Foo, int, funzioneDiConfronto> fooMap;
+fooMap[Foo(1)] = 1;
+fooMap.find(Foo(1)); -- vero
+
+///////////////////////////////////////
+// Espressioni Lambda (C++11 e superiori)
+///////////////////////////////////////
+
+// Le espressioni lambda (più semplicemente "lambda") sono utilizzate
+// per definire una funzione anonima nel punto in cui viene invocata, o
+// dove viene passata come argomento ad una funzione
+
+// Ad esempio, consideriamo l'ordinamento di un vettore costituito da una
+// coppia di interi, utilizzando il secondo elemento per confrontare
+vector<pair<int, int> > tester;
+tester.push_back(make_pair(3, 6));
+tester.push_back(make_pair(1, 9));
+tester.push_back(make_pair(5, 0));
+
+// Passiamo una lambda come terzo argomento alla funzione di ordinamento
+// `sort` è contenuta nell'header <algorithm>
+sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs) {
+ return lhs.second < rhs.second;
+});
+
+// Nota bene la sintassi utilizzata nelle lambda:
+// [] serve per "catturare" le variabili.
+// La "Lista di Cattura" definisce tutte le variabili esterne che devono essere disponibili
+// all'interno della funzione, e in che modo.
+// La lista può contenere:
+// 1. un valore: [x]
+// 2. un riferimento: [&x]
+// 3. qualunque variabile nello scope corrente, per riferimento [&]
+// 4. qualunque variabile nello scope corrente, per valore [=]
+// Esempio:
+
+vector<int> id_cani;
+// numero_cani = 3;
+for(int i = 0; i < 3; i++) {
+ id_cani.push_back(i);
+}
+
+int pesi[3] = {30, 50, 10};
+
+// Mettiamo che vuoi ordinare id_cani in base al peso dei cani
+// Alla fine, id_cani sarà: [2, 0, 1]
+
+// Le lambda vengono in aiuto
+
+sort(id_cani.begin(), id_cani.end(), [&pesi](const int &lhs, const int &rhs) {
+ return pesi[lhs] < pesi[rhs];
+});
+// Nota come abbiamo catturato "pesi" per riferimento nell'esempio.
+// Altre informazioni sulle lambda in C++: http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
+
+///////////////////////////////
+// Ciclo For semplificato(C++11 e superiori)
+///////////////////////////////
+
+// Puoi usare un ciclo for per iterare su un tipo di dato contenitore
+int arr[] = {1, 10, 3};
+
+for(int elem: arr) {
+ cout << elem << endl;
+}
+
+// Puoi usare "auto" senza preoccuparti del tipo degli elementi nel contenitore
+// Ad esempio:
+
+for(auto elem: arr) {
+ // Fai qualcosa con `elem`
+}
+
///////////////////////
// Roba divertente
//////////////////////
@@ -855,20 +944,188 @@ Foo f1;
f1 = f2;
-// Come deallocare realmente le risorse all'interno di un vettore:
-class Foo { ... };
-vector<Foo> v;
-for (int i = 0; i < 10; ++i)
- v.push_back(Foo());
+///////////////////////////////////////
+// Tuple (C++11 e superiori)
+///////////////////////////////////////
+
+#include<tuple>
+
+// Concettualmente le tuple sono simili alle strutture del C, ma invece di avere
+// i membri rappresentati con dei nomi, l'accesso agli elementi avviene tramite
+// il loro ordine all'interno della tupla.
+
+// Cominciamo costruendo una tupla.
+// Inserire i valori in una tupla
+auto prima = make_tuple(10, 'A');
+const int maxN = 1e9;
+const int maxL = 15;
+auto seconda = make_tuple(maxN, maxL);
+
+// Vediamo gli elementi contenuti nella tupla "prima"
+cout << get<0>(prima) << " " << get<1>(prima) << "\n"; // stampa : 10 A
+
+// Vediamo gli elementi contenuti nella tupla "seconda"
+cout << get<0>(seconda) << " " << get<1>(seconda) << "\n"; // stampa: 1000000000 15
+
+// Estrarre i valori dalla tupla, salvandoli nelle variabili
+int primo_intero;
+char primo_char;
+tie(primo_intero, primo_char) = prima;
+cout << primo_intero << " " << primo_char << "\n"; // stampa : 10 A
+
+// E' possibile creare tuple anche in questo modo
+tuple<int, char, double> terza(11, 'A', 3.14141);
+
+// tuple_size ritorna il numero di elementi in una tupla (come constexpr)
+cout << tuple_size<decltype(terza)>::value << "\n"; // stampa: 3
+
+// tuple_cat concatena gli elementi di tutte le tuple, nell'esatto ordine
+// in cui sono posizionati all'interno delle tuple stesse
+auto tupla_concatenata = tuple_cat(prima, seconda, terza);
+// tupla_concatenata diventa = (10, 'A', 1e9, 15, 11, 'A' ,3.14141)
+
+cout << get<0>(tupla_concatenata) << "\n"; // stampa: 10
+cout << get<3>(tupla_concatenata) << "\n"; // stampa: 15
+cout << get<5>(tupla_concatenata) << "\n"; // stampa: 'A'
+
+
+/////////////////////
+// Contenitori
+/////////////////////
+
+// I Contenitori della "Standard Template Library", ovvero la libreria standard
+// dei template contenuti nel C++, sono template predefiniti.
+// I Contenitori si occupano di come allocare lo spazio per gli elementi contenuti,
+// e forniscono funzioni per accedervi e manipolarli
+
+// Vediamo alcuni tipi di contenitori:
+
+// Vector (array dinamici/vettori)
+// Permettono di definire un vettore, o una lista di oggetti, a runtime
+#include<vector>
+vector<Tipo_Dato> nome_vettore; // usato per inizializzare un vettore
+cin >> val;
+nome_vettore.push_back(val); // inserisce il valore di "val" nel vettore
+
+// Per iterare in un vettore, abbiamo due possibilità:
+// Ciclo normale
+for(int i=0; i<nome_vettore.size(); i++)
+// Cicla dall'indice zero fino all'ultimo
+
+// Iteratore
+vector<Tipo_Dato>::iterator it; // inizializza l'iteratore per il vettore
+for(it=nome_vettore.begin(); it!=nome_vettore.end();++it)
+// Nota che adesso non cicla più sugli indici, ma direttamente sugli elementi!
+
+// Per accedere agli elementi del vettore
+// Operatore []
+var = nome_vettore[indice]; // Assegna a "var" il valore del vettore all'indice dato
+
+
+// Set (insiemi)
+// Gli insiemi sono contenitori che memorizzano elementi secondo uno specifico ordine.
+// Gli insiemi vengono per lo più utilizzati per memorizzare valori unici, secondo
+// un ordine, senza scrivere ulteriore codice.
+
+#include<set>
+set<int> insieme; // Inizializza un insieme di interi
+insieme.insert(30); // Inserisce il valore 30 nell'insieme
+insieme.insert(10); // Inserisce il valore 10 nell'insieme
+insieme.insert(20); // Inserisce il valore 20 nell'insieme
+insieme.insert(30); // Inserisce il valore 30 nell'insieme
+// Gli elementi dell'insieme sono:
+// 10 20 30
+
+// Per cancellare un elemento
+insieme.erase(20); // Cancella l'elemento con valore 20
+// L'insieme contiene adesso: 10 30
+
+// Per iterare su un insieme, usiamo gli iteratori
+set<int>::iterator it;
+for(it=insieme.begin();it<insieme.end();it++) {
+ cout << *it << endl;
+}
+// Stampa:
+// 10
+// 30
+
+// Per svuotare il contenitore usiamo il metodo "clear"
+insieme.clear();
+cout << insieme.size();
+// Stampa: 0
+
+// Nota: per permettere elementi duplicati, possiamo usare "multiset"
+
+// Map (mappa/tabella di hash)
+// Le mappe servono per memorizzare un elemento, detto chiave, a cui viene
+// associato un valore, il tutto secondo uno specifico ordine.
+
+#include<map>
+map<char, int> mia_mappa; // Inizializza una mappa che usa i char come chiave, e gli interi come valore
+
+mia_mappa.insert(pair<char,int>('A',1));
+// Inserisce il valore 1 per la chiave A
+mia_mappa.insert(pair<char,int>('Z',26));
+// Inserisce il valore 26 per la chiave Z
+
+// Per iterare
+map<char,int>::iterator it;
+for (it=mia_mappa.begin(); it!=mia_mappa.end(); ++it)
+ std::cout << it->first << "->" << it->second << '\n';
+// Stampa:
+// A->1
+// Z->26
+
+// Per trovare il valore corrispondente ad una data chiave
+it = mia_mappa.find('Z');
+cout << it->second;
+// Stampa: 26
+
+
+///////////////////////////////////
+// Operatori logici e bitwise(bit-a-bit)
+//////////////////////////////////
+
+// La maggior parte di questi operatori in C++ sono gli stessi degli altri linguaggi
+
+// Operatori logici
+
+// Il C++ usa la "Short-circuit evaluation" per le espressioni booleane. Cosa significa?
+// In pratica, in una condizione con due argomenti, il secondo viene considerato solo se
+// il primo non basta a determinate il valore finale dell'espresione.
+
+true && false // Effettua il **and logico** e ritorna falso
+true || false // Effettua il **or logico** e ritorna vero
+! true // Effettua il **not logico** e ritorna falso
+
+// Invece di usare i simboli, si possono usare le keyword equivalenti
+true and false // Effettua il **and logico** e ritorna falso
+true or false // Effettua il **or logico** e ritorna vero
+not true // Effettua il **not logico** e ritorna falso
+
+// Operatori bitwise(bit-a-bit)
+
+// **<<** Operatore di Shift a Sinistra
+// << sposta i bit a sinistra
+4 << 1 // Sposta a sinistra di 1 i bit di 4, ottenendo 8
+// x << n in pratica realizza x * 2^n
+
+
+// **>>** Operatore di Shift a Destra
+// >> sposta i bit a destra
+4 >> 1 // Sposta a destra di 1 i bit di 4, ottenendo 2
+// x >> n in pratica realizza x / 2^n
-// La riga seguente riduce la dimensione di v a 0, ma il distruttore non
-// viene chiamato e dunque le risorse non sono deallocate!
-v.empty();
-v.push_back(Foo()); // Il nuovo valore viene copiato nel primo Foo che abbiamo inserito
+~4 // Effettua il NOT bit-a-bit
+4 | 3 // Effettua il OR bit-a-bit
+4 & 3 // Effettua il AND bit-a-bit
+4 ^ 3 // Effettua il XOR bit-a-bit
-// Distrugge realmente tutti i valori dentro v. Vedi la sezione riguardante gli
-// oggetti temporanei per capire come mai funziona così.
-v.swap(vector<Foo>());
+// Le keyword equivalenti sono
+compl 4 // Effettua il NOT bit-a-bit
+4 bitor 3 // Effettua il OR bit-a-bit
+4 bitand 3 // Effettua il AND bit-a-bit
+4 xor 3 // Effettua il XOR bit-a-bit
```
Letture consigliate: