Perché dovrei imparare C ++ 11, avendo conosciuto C e C ++? [chiuso]

27

Sono un programmatore in C e C ++, anche se non mi attengo a nessuna delle due lingue e scrivo una combinazione delle due. A volte avere codice in classi, possibilmente con sovraccarico dell'operatore o modelli e l'STL così eccezionale è ovviamente un modo migliore. A volte l'uso di un semplice puntatore a funzione C è molto più leggibile e chiaro. Quindi trovo la bellezza e la praticità in entrambe le lingue. Non voglio entrare nella discussione di "Se li mescoli e compili con un compilatore C ++, non è più un mix, è tutto in C ++" Penso che capiamo tutti cosa intendo mescolandoli. Inoltre, non voglio parlare di C vs C ++, questa domanda riguarda C ++ 11.

C ++ 11 introduce ciò che penso siano cambiamenti significativi nel funzionamento di C ++, ma ha introdotto molti casi speciali, eccezioni e irregolarità che cambiano il modo in cui le diverse caratteristiche si comportano in circostanze diverse, ponendo restrizioni sull'ereditarietà multipla, identificatori che agiscono come parole chiave, estensioni di stringhe letterali, cattura della funzione lambda, ecc.

So che ad un certo punto in futuro, quando dirai C ++, tutti supporteranno C ++ 11. Proprio come quando dici C al giorno d'oggi, probabilmente stai parlando di C99. Questo mi fa pensare all'apprendimento di C ++ 11. Dopotutto, se voglio continuare a scrivere codice in C ++, a un certo punto potrei iniziare a usare quelle funzioni semplicemente perché i miei colleghi hanno.

Prendi C per esempio. Dopo tanti anni, ci sono ancora molte persone che imparano e scrivono codice in C. Perché? Perché la lingua è buona. Ciò che significa buono è che, segue molte delle regole per creare un buon linguaggio di programmazione. Quindi oltre ad essere potente (che è facile o difficile, quasi tutti i linguaggi di programmazione sono), C è regolare e ha poche eccezioni, se ce ne sono. C ++ 11 tuttavia, io non la penso così. Non sono sicuro che le modifiche introdotte in C ++ 11 migliorino il linguaggio.

Quindi la domanda è: Perché dovrei imparare C ++ 11?

    
posta GlenH7 09.11.2011 - 01:42
fonte

10 risposte

24

Dovresti impararlo se pensi di aver bisogno di conoscerlo in futuro per ottenere un lavoro. Se sei sicuro che rimarrai commercializzato nel mondo del lavoro come un C / C ++ [e qualsiasi altra cosa tu possa conoscere], allora non apprenderlo. Se il tuo capo ti dice di usare C ++ 11, dì "no, non lo faccio". Se ti spara, vai a lavorare da qualche altra parte. Impara C ++ 11 quando prevedi che presto non sarai in grado di trovare un impiego soddisfacente con le abilità che conosci attualmente.

Volevo chiarire la mia logica: non sono anti-C ++ 11. Sto solo dicendo che potresti generalizzare la domanda dell'OP a "Perché dovrei imparare X". Non ho mai imparato ML, schema o haskell perché ho un lavoro con C e C ++. Sono sicuro che quelle lingue sono utili a qualcuno, ma non sono utili per me da imparare in questo momento. Se qualcuno mi offrisse dei bei soldi per programmare in ML, potrei provare a impararlo.

    
risposta data 15.11.2011 - 22:48
fonte
83

È semplice. C ++ 11 rende il codice estremamente più semplice, più pulito da scrivere e più veloce.

nullptr è un miglioramento VAST rispetto al vecchio 0 . È sicuro per il tipo e non converte quando non dovrebbe, a differenza di 0 . È una cosa buona che nullptr non convertirà in int . Non ha senso che ciò accada del tutto. Sai cosa ha trovato il Comitato C ++ quando hanno provato a considerare #define NULL nullptr ? Roba come char c = NULL; . Quanto è terribile? L'unica ragione per cui qui c'è un'eccezione è che bool è considerato un tipo integrale, il che è abbastanza sbagliato, ma era presente in C ++ prima e in C. Il fatto che nullptr non venga convertita è buona , è grande e dovresti amarlo.

O che ne dici di riferimenti di valore e modelli variadici? Codice più veloce e più generico. Questa è una vittoria totale proprio lì.

E i miglioramenti della libreria? Cose come function , unique_ptr e shared_ptr sono molto migliori di quelle precedenti, è impossibile sostenere che il modo C ++ 03 fosse migliore.

#define adding_func(x, y) ((x)+(y))

Non è nemmeno lontanamente equivalente. I macro sono cattivi per sei miliardi di ragioni. Non ho intenzione di citarli tutti qui, ma è risaputo che le macro dovrebbero essere evitate per quasi tutti gli scopi che possono essere evitati. Che cosa hai intenzione di fare quando è

#define add_twice(x) (x + x)

Oh aspetta, spero che tu non abbia incrementato o qualcosa su x . Quale la versione della funzione template è totalmente immune. Spero anche che tu non apprezzi namespace , ad esempio.

Then you open yourself to a world of undefined behavior for using external variables whose scopes are already finished.

In un'API funzionale, ad es. Algoritmi STL, quindi il riferimento va bene. Se si tratta di una richiamata memorizzata, è necessario acquisire per valore. Qualunque documentazione tu abbia sulla funzione dovrebbe indicare chiaramente che è necessario. Il fatto che il codice sia scritto in una lambda è irrilevante per il problema del riferimento alle variabili locali: se si passa un oggetto a funzione regolare, si avrà lo stesso identico problema. E non è un problema. Affatto. Perché è intrinsecamente ovvio quando puoi e non puoi fare riferimento a variabili locali.

Take C for example. After so many years, there are still many people learning and writing code in C. Why?

Ci sono molte persone che non si lavano i denti al mattino. Ci sono molti assassini, stupratori e prostitute. E i politici. Persone che si suicidano Vorresti sostenere che ciò rende queste attività buone o utili? Ovviamente no. È un errore logico che solo perché qualcuno lo ha fatto, quindi deve essere buono o utile.

C è ancora in fase di scrittura per tre motivi: perché C ++ è una cagna da implementare, per esempio in modalità embedded o kernel; perché le codebase legacy sono scritte in C e costerebbero troppo per l'aggiornamento, anche se questo è discutibile dato l'eccellente interoperabilità C di C ++; e perché le persone che lo scrivono non sanno come programmare. Questo è tutto. Non c'è altra ragione per scrivere C.

If you take C or the old style C++, you wouldn't find many exceptions.

Che ne dici dei patetici array in stile C, per un semplice esempio? Il numero di persone che non riescono a ottenere matrici e puntatori nella loro testa è osceno. Per non parlare del fatto che la libreria C Standard è incredibilmente pericolosa.

I tuoi argomenti principali sono pieni di errori logici e incomprensioni.

    
risposta data 09.11.2011 - 02:30
fonte
28

C ++ 11 non è una nuova lingua; è solo un'estensione / modifica di C ++ che già conosci. C ++ 11 proprio come qualsiasi altro linguaggio di programmazione è costituito da funzionalità. Molti di loro erano lì da prima, alcuni di loro sono nuovi. Ma la tua domanda è davvero, dovrei imparare tutte le caratteristiche del linguaggio (in questo caso C ++ 11), o solo familiarizzare con il 90% di esso?

IMO anche se non stai utilizzando tutta la lingua, dovresti almeno leggere su ciò che le nuove funzionalità fanno per te. Molti di essi sono stati introdotti per rendere più facile scrivere la libreria / il codice framework (soprattutto i template) (ad esempio, prima che C ++ 11 fosse perfetto per l'inoltro perfetto), ma se non hai mai avuto bisogno di quelle funzionalità, è probabile che tu abbia vinto Si noti che queste funzionalità sono state aggiunte in C ++ 11.

D'altra parte, se in precedenza si è dilungato nello scrivere la libreria / il codice base che imita alcune funzionalità di STL / Boost e si è trovato limitato dal linguaggio perché sei arrivato al 95% ad avere un ambiente molto elegante, elegante soluzione ma poi sei stato fermato perché hai scoperto che la lingua semplicemente non supporta quello che vuoi, ti renderai conto della potenza davvero fantastica del C ++ 11. Da quando il nostro team è passato a VS2010 (e abbiamo scoperto Boost nel processo), sono stato in grado di estrarre un pazzo codice fantastico, che sarebbe semplicemente impossibile prima di cose come i riferimenti a valori r e l'inoltro dei parametri del modello.

Anche cose come lambda possono sembrare estranee, ma non introducono un nuovo costrutto. Invece, fanno ciò che prima avevamo molto più facile da scrivere. In precedenza ogni funzione lambda doveva essere una classe separata. Ora è solo {... code ...}. Love it.

La chiave è non guardare queste funzionalità e pensare quanto scoraggiante è la lista. Invece, usa C ++ come fai normalmente e quando ti imbatti in uno scenario in cui queste nuove funzionalità di C ++ 11 sono utili (più del 90% delle persone non arriverà mai a quel punto), sarai molto felice che l'estensione alla lingua è stato fatto. Per ora, ti suggerirei di imparare abbastanza sul linguaggio per sapere cosa c'è, non necessariamente come usarlo tutto.

    
risposta data 09.11.2011 - 02:19
fonte
18

Is it so hard to write a function, that you have to write the content of the function inline with the code, besides giving it no name?

Quando lo fai scorri verso l'alto o apri un nuovo file sorgente e aggiungi lì la definizione della funzione. Quindi devi tornare indietro e continuare su ciò a cui stavi lavorando, cosa che ti distrae in una certa misura.

Oltre a questo, quando altre persone stanno leggendo il tuo codice un lambda potrebbe essere più autodocumentante in alcuni casi, invece di dire "Oh, che cosa fa questa funzione?" e saltando alla sua dichiarazione si può solo dare un'occhiata a ciò che sta facendo al suo posto.

C'è una bella chiacchierata di Herb Sutter su lambda, forse ti può convincere meglio:

link

Well, why don't you just write the code there instead of making it a lambda-function?

Perché non puoi farlo quando usi gli algoritmi STL o qualsiasi funzione che stai utilizzando che richiede il passaggio di una funzione.

#define adding_func(x, y) ((x)+(y))

Non c'è modo di giustificare questo uso al posto di lambda, non puoi riempire il tuo codice con macro ovunque. Le macro e le funzioni hanno scopi diversi e una, in generale, non sostituisce l'altra.

template<class Lhs, class Rhs>
auto adding_func(const Lhs &lhs, const Rhs &rhs)
                -> decltype(lhs+rhs) {return lhs + rhs;}

Sono d'accordo, questo è brutto. Comunque mi ricordo di aver detto "perché diavolo dovrei capire il tipo di questa espressione anche se il compilatore può dedurlo?" in molti casi. Questo potrebbe aiutare molto in quei momenti.

Per riassumere:

Anche se le nuove funzionalità di C ++ 11 sembrano brutte nella loro sintassi, penso che ci si possa abituare in breve tempo. All'inizio, ogni nuovo linguaggio è difficile da imparare; immagina la prima volta che hai imparato a scrivere un'intera classe: inserendo la dichiarazione nel file di intestazione, senza dimenticare il punto e virgola in più alla fine, inserendo le definizioni nel file di origine, incluso il file di intestazione, assicurando al tempo stesso una protezione per prevenire inclusioni multiple, senza dimenticare l'operatore di risoluzione scope nelle dichiarazioni delle funzioni membro e così via ...

Ma sono abbastanza sicuro che dopo aver scritto alcune classi ci si abitui e non si pensi alla complessità di questo processo: perché sai che una classe rende il tuo lavoro di programmatore molto più facile, e l'utilità che stai guadagnando da questo nuovo costrutto è molto più grande della perdita di utilità durante il periodo in cui stavi cercando di imparare la lingua . Penso che questo possa essere il motivo per cui si dovrebbe provare ad imparare, o usare C ++ 11 in modo simile.

    
risposta data 09.11.2011 - 04:11
fonte
8

In realtà l'OP ha alcuni punti, come della maggior parte delle risposte. Ma sono "distanti" nella visione. Il C ++ (incluso il sottoinsieme C) ha una lunga storia in cui un certo numero di funzionalità sono state aggiunte nel tempo, alcune delle quali utilizzate più o meno frequentemente e, attraverso l'uso e gli errori, perfezionate in altri e in altri.

A volte capita che, dopo aver introdotto una nuova funzione, sia più necessaria una vecchia, o si senta in contraddizione con essa. Un linguaggio "pulito" dovrebbe essere auto-coerente così com'è, e le funzioni non più necessarie dovrebbero essere rimosse.

Ma l'aggiunta non distrugge nulla. Rimozione (o modifica) interrompe il codice esistente che è ancora in produzione, quindi qualsiasi funzione aggiunta, devi fare attenzione a non violare il codice esistente (in particolare, non romperlo silenziosamente , facendolo fare cose diverse come previsto)

Devi imparare tutto questo? Sì, perché tutte le funzionalità sono, nel bene o nel male, prima o poi, usate. Che questa sia una buona cosa per la "qualità" linguistica (ammettere che c'è una misura obiettivo per esso) è un'altra storia: per quanto tempo dovrebbe essere mantenuta la retrocompatibilità? difficile trovare una risposta, quando qualcuno dice 3 anni e altri 50.

L'alternativa a mantenere C ++ più "regolare" è ... interromperla più spesso, con un riavvio immediato. Ma non sarà più C ++.

Ci sono anche dei tentativi per farlo (pensate a D, per esempio: molto più ortogonale del C ++ (anche 11) in realtà), ma quanto sono popolari? Tra le ragioni del loro difficile avere lo slancio è l'incompatibilità con molti codici esistenti che devono ancora funzionare.

C ++ 11, per me, è chiaramente un compromesso tra nuove esigenze e compatibilità con le versioni precedenti. Ciò ha provocato un certo "imbarazzo" delle sue specifiche e della sua implementazione. Fino a quando il costo di quella "confusione" è inferiore al costo dell'incompatibilità ... devi andartene con quel compromesso.

Se non puoi più tollerarlo, ... meglio considerare un'altra lingua più giovane. C ++ semplicemente non può essere semplificato in questo senso. Non a questa età.

    
risposta data 09.11.2011 - 13:37
fonte
7

Anche se decidi di ignorare le nuove funzionalità di C ++ 11, ne trarrai comunque beneficio perché la libreria standard C ++ le utilizzerà. Ad esempio, in C ++ 98 la presenza di una variabile di tipo vector<string> è stata probabilmente un disastro di prestazioni a causa del numero di copie necessarie per la crescita del vettore. Con C ++ 11 move constructor, è un non-problema. In effetti, vorrei che C ++ 11 ci portasse più nuove funzionalità, non meno - specialmente nella Libreria standard.

    
risposta data 09.11.2011 - 14:47
fonte
6

After so many years, there are still many people learning and writing code in C. Why? Because the language is good.

In primo luogo, la maggior parte degli studenti in questi giorni sta imparando Java o .NET, non C. In secondo luogo, le persone usano ancora C non solo per i suoi vantaggi come linguaggio, ma soprattutto perché c'è una quantità enorme di software esistente scritto in C che deve essere mantenuto ed esteso, e perché in molti casi (ad esempio piattaforme embedded) un compilatore C è tutto ciò che esiste. Per inciso, questi sono alcuni dei motivi per cui le persone scrivono ancora COBOL.

È molto raro che un programmatore del settore inizi a lavorare su un progetto nuovo di zecca che non sia legato a una base di codice esistente e che continui a lavorare da solo. Quindi, la ragione per imparare C ++ 11 è che è probabile che tu abbia a che fare con codice scritto da altre persone, che usa le nuove funzionalità. Inoltre, le funzionalità aggiunte sono state aggiunte per un motivo. Una volta che li impari e li usi, potresti venire ad apprezzarli.

    
risposta data 09.11.2011 - 02:16
fonte
5
  • L'assemblaggio è stato creato perché alla gente non piaceva scrivere codice macchina
  • C è stato creato perché alla gente non piaceva scrivere assembly
  • C ++ è stato creato perché alla gente non piaceva scrivere C
  • C ++ 11 è stato creato perché alla gente non piaceva scrivere C ++

Arriverete ad un punto della vostra carriera in C ++, dove dite a voi stessi, "Certo che i funtori siano più semplici," o "Perché NULL è un int?" e quindi capirai C ++ 11.

    
risposta data 09.11.2011 - 04:36
fonte
4

L'apprendimento è sempre vantaggioso. La conoscenza è potere.

Questa è la risposta, in pratica. Tutto il resto è solo dettagli su come esattamente puoi trarne beneficio e quali poteri hai a saperlo, e sono così numerosi che ogni enumerazione sarebbe incompleta.

Un esempio è la tua domanda. Non potresti nemmeno chiederlo senza averne imparato almeno un po '.

E come ho commentato - la vera preoccupazione non è il perché imparare, ma perché utilizzare . E questa è una domanda completamente diversa.

    
risposta data 09.11.2011 - 01:57
fonte
4

Dovresti imparare C ++ 11 perché le funzionalità aggiunte ti permettono di scrivere codice migliore. Alcune persone hanno menzionato la sicurezza di tipo dei puntatori NULL e dei lambda, che sono molto carini. Ma voglio attirare l'attenzione su quello che ritengo sia il cambiamento più drammatico in C ++ 11, specialmente in un grande ambiente di produzione: spostare la semantica.

C ++ 11 supporta nozioni separate di "spostamento" e "copia". Nel normale C ++, abbiamo solo l'operatore = che fondamentalmente fa entrambe le cose. Ma in realtà, stiamo esprimendo due idee separate con un solo operatore, che è pericoloso.

L'esempio più ovvio di dove questo è utile è il nuovo unique_ptr. Ha tutte le migliori caratteristiche del vecchio auto_ptr e scoped_ptr. Supponiamo di voler avere un puntatore che è garantito essere l'unico puntatore che punta a un oggetto. Come gestiamo a = b? Bene, prima eravamo bloccati, potevi o non accettarlo completamente (come scoped_ptr), o potremmo fare ciò che auto_ptr fa dove a = b ruba la proprietà da b. Questo comportamento di auto_ptr è molto confuso perché a = b cambia effettivamente b. unique_ptr gestisce questo: a = b non è consentito, ma hai un = std :: move (b) per sottrarre la proprietà. Come è utile? Dove, c'è una versione separata (sovraccarico) di swap che usa semantica di movimento invece di copiare la semantica. Ciò significa che quel unique_ptr può essere scambiato, nessun problema. Ciò significa che unique_ptr, diversamente da auto_ptr, è sicuro da usare in un contenitore e quindi dice sort. unique_ptr è in pratica il tutto e termina la gestione della memoria sicura quando non sono necessari più puntatori sullo stesso oggetto.

Un altro grande esempio: supponiamo di avere un oggetto che non è copiabile. Questo è utile in una serie di situazioni. Non puoi mai restituire questo oggetto da una funzione, perché quando termina la funzione, copia fuori tutto ciò che stai restituendo. La cosa ironica è che di solito il compilatore in realtà lo ottimizza (non viene effettivamente copiato nulla alla fine, il valore di ritorno viene creato all'indirizzo di assegnazione finale). Ma questo non ha nulla a che fare con il motivo per cui lo abbiamo reso inconciliabile; il ritorno da una funzione è in realtà solo spostando l'oggetto dall'ambito della funzione all'esterno. Ora puoi scrivere oggetti che sono non riscontrabili, ma sono mobili e questi oggetti possono essere restituiti dalle funzioni.

Spostare la semantica rende molto più facile scrivere codice che non perderà ed è thread-safe.

    
risposta data 10.10.2013 - 18:29
fonte

Leggi altre domande sui tag