Quali pratiche C # dovrebbero essere evitate in C ++?

45

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 ++.

    
posta Donny V. 15.02.2011 - 19:55
fonte

11 risposte

48
  • 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:

  • Leggi gli articoli da Effective C ++ Series di Scott Meyers. Dopo di loro, leggi anche Eccezionale serie C ++ di Herb Sutter.

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!

    
risposta data 15.02.2011 - 19:58
fonte
18

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 using new), 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.

    
risposta data 15.02.2011 - 20:03
fonte
16

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.

    
risposta data 15.02.2011 - 19:56
fonte
13

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.

    
risposta data 15.02.2011 - 20:01
fonte
10

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.

    
risposta data 15.02.2011 - 20:00
fonte
7

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.

    
risposta data 04.01.2013 - 15:21
fonte
6

Dimentica finalmente try- (catch-) e abituati a fare l'allocazione delle risorse / deallocazione tramite costruttori / distruttori (RAII).

    
risposta data 15.02.2011 - 20:01
fonte
3

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.

    
risposta data 16.02.2011 - 04:41
fonte
1

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.

    
risposta data 15.02.2011 - 19:58
fonte
1

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.

    
risposta data 15.02.2011 - 19:58
fonte
1

Gestione della memoria, attenzione alle perdite di memoria e abituarsi a non disporre della garbage collection automatica.

    
risposta data 15.02.2011 - 19:59
fonte

Leggi altre domande sui tag