Innanzitutto, alcune regole pratiche:
Utilizzare std::unique_ptrcome puntatore intelligente senza spese generali. Non dovresti preoccuparti di puntatori non elaborati molto spesso. std::shared_ptrè anche inutile nella maggior parte dei casi. Un desiderio di proprietà condivisa spesso tradisce in primo luogo una mancanza di pensiero sulla proprietà.
Utilizzare std::arrayper matrici di lunghezza statica e std::vectordinamica.
Utilizzare ampiamente algoritmi generici, in particolare:
<algorithm>
<numeric>
<iterator>
<functional>
Utilizzare autoe decltype()ovunque giovano alla leggibilità. In particolare, quando vuoi dichiarare una cosa, ma di un tipo che non ti interessa come un iteratore o un tipo di modello complesso, usa auto. Quando vuoi dichiarare una cosa in termini di tipo di un'altra cosa, usa decltype().
Rendi le cose sicure quando puoi. Quando hai affermazioni che impongono gli invarianti su un particolare tipo di cosa, quella logica può essere centralizzata in un tipo. E questo non comporta necessariamente alcun sovraccarico di runtime. Va anche detto che i cast in stile C ( (T)x) dovrebbero essere evitati a favore dei cast più espliciti (e ricercabili!) In stile C ++ (ad es static_cast.).
Infine, sapere come la regola di tre:
- Distruttore
- Copia costruttore
- Operatore di assegnazione
È diventata la regola del cinque con l'aggiunta del costruttore di spostamenti e dell'operatore di assegnazione di spostamenti. Comprendi i riferimenti ai valori in generale e come evitare la copia.
C ++ è un linguaggio complesso, quindi è difficile da caratterizzare il modo migliore per utilizzare tutto di esso. Ma le pratiche del buon sviluppo del C ++ non sono cambiate sostanzialmente con il C ++ 11. Dovresti comunque preferire i contenitori gestiti dalla memoria rispetto alla gestione manuale della memoria: i puntatori intelligenti consentono di farlo in modo efficiente.
Direi che il moderno C ++ è in effetti per lo più privo di gestione manuale della memoria: il vantaggio del modello di memoria del C ++ è che è deterministico , non manuale. Deallocations prevedibili rendono le prestazioni più prevedibili.
Per quanto riguarda un compilatore, G ++ e Clang sono entrambi competitivi in termini di funzionalità C ++ 11 e stanno rapidamente recuperando le loro carenze. Non uso Visual Studio, quindi non posso parlare né a favore né contro.
Infine, una nota su std::for_each: evitarlo in generale.
transform, accumulateE erase- remove_ifsono il buon vecchio funzionali map, folde filter. Ma for_eachè più generale e quindi meno significativo: non esprime alcun intento diverso dal looping. Oltre a ciò, viene utilizzato nelle stesse situazioni di range-based fored è sintatticamente più pesante, anche se usato senza punti. Ritenere:
for (const auto i : container)
std::cout << i << '\n';
std::for_each(container.begin(), container.end(), [](int i) {
std::cout << i << '\n';
});
for (const auto i : container)
frobnicate(i);
std::for_each(container.begin(), container.end(), frobnicate);