Attualmente sto insegnando a me stesso C ++. Sono molto abile in C # e mi chiedevo quali pratiche comuni in C # possano portare a difficoltà in C ++ e cosa invece dovrebbe fare un programmatore C ++.
Prima di tutto, devi imparare RAII: Acquisizione della risorsa è inizializzazione
Assicurati di utilizzare new
, quindi non dimenticare di utilizzare delete
nel tuo programma. Non mischiare new
con malloc
e delete
con free
. new
e malloc
non sono intercambiabili, né delete
e free
. Come in C #, non scrivi distruttore (di solito), quindi in C ++ hai specificamente bisogno di imparare come usare efficacemente destructor per liberare memoria e altre risorse! Una volta che conosci questi concetti, prova a progettare le cose in modo RAII per gestire efficacemente le risorse, in modo che tu non debba occuparti di new
e delete
esplicitamente nel tuo codice ovunque.
Deve apprendere quali sono i punti di sequenza , comportamento indefinito , comportamento non specificato , comportamento definito dall'implementazione in C ++. Dato che C # non ha questi concetti, significa che non hai mai sentito questi termini mentre programmavi in C #, quindi è molto probabile che tu scriverà codice C ++ (come a[++i]= i
, i+=++i
) il cui comportamento è non ben definito. Quindi ti consiglierei di leggere questi argomenti:
PS: Dato che ho parlato di nuovo, cancella, memoria raw ecc., allora aggiungo una differenza interessante tra C ++ e C #:
In C ++, this
è un puntatore, mentre in C # this
è un riferimento!
Il più fondamentale è ovviamente legato alla mancanza di un garbage collector:
don't use
new
any more than necessary. Understand the RAII idiom: allocate your objects on the stack (without usingnew
), and let their destructors take care of cleaned up allocated memory for you. Or use smart pointers to handle some of this for you.
Oltre a questo, direi che ci sono alcuni problemi stilistici a cui dovresti abituarti. C # è ancora, nonostante il suo flirt con la programmazione funzionale, un linguaggio OOP.
C ++ è un linguaggio multi-paradigma, e nel moderno C ++, l'OOP non svolge un ruolo molto importante. Dovresti assolutamente dare un'occhiata alla programmazione generica, però. Comprendere come utilizzare l'STL (le strutture dati, gli iteratori e gli algoritmi nella libreria standard). E sentirsi un po 'sporchi quando si scrive una funzione virtuale.
La gestione automatica della memoria e la garbage collection sono probabilmente qualcosa che potresti mancare in C ++. Ma IMHO quello che ti mancherà di più è la coerenza del framework .NET in cui hai dato per scontate molte cose semplicemente perché sono integrate nel BCL.
Il problema più grande che ho visto è la tendenza a nuovi oggetti dappertutto e ad usarli sullo heap. Certo, potrebbero prendersi molta cura eliminandoli perché non c'è GC, ma il problema è l'allocazione in primo piano. C ++ funziona meglio mettendo cose in pila e copiandole. Se hai ancora bisogno di un singolo oggetto condiviso, usa shared_ptr per contenerlo.
Attenzione, questo non è esclusivo per gli sviluppatori di C #, ho visto alcuni sviluppatori Web fare lo stesso genere di cose.
La raccolta dei dati inutili è grande, ma se usi puntatori intelligenti puoi evitare la maggior parte dei problemi.
Un problema più pervasivo è quello della sicurezza delle eccezioni. Questa non è tanto un'abitudine C # che ti metterà nei guai, ma una mancanza di uno. In C #, ottieni sicurezza con using
blocchi e finally
gestori. Il C ++ non ha né Quello che hai è una tecnica chiamata RAII (l'acquisizione delle risorse è l'inizializzazione), dove le classi sono progettate attentamente in modo che i loro distruttori puliscano le cose. Quindi, anziché utilizzare un blocco using
per aprire un file, imposterai lo stack dell'oggetto file e il distruttore eseguirà lo svuotamento e la chiusura del file. Si occupa di progettare e utilizzare le classi in questo modo, ma una volta che si forma l'abitudine, il codice può essere abbastanza sicuro. È solo un approccio diverso. In generale, il fatto che C ++ abbia l'allocazione dello stack di oggetti richiederà alcuni aggiustamenti.
RAII è sicuramente uno degli aspetti chiave del C ++ da apprendere. Altri poster lo hanno descritto, ma aggiungerò che è abbastanza simile al IDisposable di C # . interfaccia combinata con utilizzando parola chiave.
Fai attenzione ai tipi char
e string
in C ++, sono cresciuti da molti anni di esperienza (amara) e ci sono diversi tipi. In C # sono tutti Unicode (ho dimenticato la codifica), ma in C ++ un char
dipende in genere dalla code page del sistema. Ad esempio, Windows USA-Inglese utilizza una tabella codici di Windows 1252 per impostazione predefinita per programmi non Unicode. Le pagine di codice sono difficili da gestire e soggette a errori, quindi utilizza wchar_t
e std::wstring
di STL. Tieni presente inoltre che le dimensioni di char
e wchar_t
sono diverse tra diversi compilatori. Molti compilatori C ++ basati su Linux usano una dimensione di carattere diversa e il consiglio è di nuovo diverso! Vedi link per ulteriori informazioni informazioni.
Sii consapevole della portata delle variabili e quando saranno distrutte. In genere è una cattiva pratica fare return new object()
in quanto il chiamante potrebbe non rendersi conto di dover ripulire il valore restituito.
Evita l'uso di puntatori nudi, invece usa unique_ptr o shared_ptr
+ Usa make_shared < > () per creare un shared_ptr. Sfortunatamente al momento non è presente l'equivalente di unique_ptr
.
Ulteriori informazioni su spostare la semantica - possono aiutare un molto con RAII. Non sono a conoscenza di un equivalente in C #
Capire cos'è un puntatore opaco . Se utilizzi l'API di Windows, ne troverai molte sotto forma di HANDLE
s.
Diffida di memorizzare elenchi (ad esempio std::vector
o std::deque
) di oggetti che possono essere ereditati in quanto ciò può portare a slicing in cui la parte ereditata della classe viene eliminata in modo da lasciare solo il tipo dichiarato.
Dimentica finalmente try- (catch-) e abituati a fare l'allocazione delle risorse / deallocazione tramite costruttori / distruttori (RAII).
Evita di programmare in C ++ come se fosse C #, questa è la pratica che dovresti evitare. In realtà impara la lingua, sono stranezze, le parti buone e gli idiomi.
Il più ovvio probabilmente sarebbe dare per scontato il garbage collection. Gli oggetti non referenziati devono essere disposti manualmente in C ++, ma in C # si ha il GC per occuparsene.
Gestione della memoria, passaggio di convenzioni e puntatori, anche se se si utilizza una libreria come Boost è probabilmente meno un problema. Tuttavia, se stai insegnando te stesso C ++ è probabilmente una buona idea non usare alcuna libreria e imparare prima le basi.
Gestione della memoria, attenzione alle perdite di memoria e abituarsi a non disporre della garbage collection automatica.