C++ version 14 er godkendt og klar

En ny version af C++ er nu godkendt som standard og er allerede tilgængelig. Der er ikke store ændringer, men mange små, i version 14.

Her er en ny version af C++, og nu skal du vente et par år, før du kan bruge det.

Sådan plejede det at være med nye standarder for programmeringssproget C++, men med godkendelsen af C++14 er der kommet anderledes fut i udviklingen: For første gang er der brugbare implementeringer klar af den nye standard, netop som C++14 er blevet vedtaget som standard. Det skriver Infoworld.

Den nye version byder ikke på drastiske ændringer af det over 30 år gamle sprog, men er højere grad en finpudsning af nyhederne fra seneste versionsskifte i 2011. Dengang fik C++ for eksempel lambda-udtryk, som nu også Java 8 har fået det, og i C++14 er der så tilføjet generiske lambda-udtryk.

Læs også: Javas chefarkitekt: Sådan bliver Java 8 mere moderne – på en konservativ måde

Generelt er C++14 en slags konsolidering, hvor der kommer mere samling på de nyskabelser, som er blevet tilføjet gennem tiden. De større ændringer bliver gemt til næste versionsskifte i 2017.

Standard C++ Foundation skriver i et blogindlæg, at der efter vedtagelsen af standarden, gennem en afstemning, nu kun er sproglig finpudsning tilbage, før C++14 kan blive publiceret som ny ISO-standard. Det formelle navn for den nye version af C++ er i øvrigt International Standard ISO/IEC 14882:2014(E) Programming Language C++.

Bjarne Stroustrup, den danske skaber af C++, har for nyligt meldt ud, at C++ trods hård konkurrence stadig er et meget populært sprog. Der er ikke noget, som kan konkurrere med hastigheden i C++, var meldingen.

Læs også: Bjarne Stroustrup: Der er stadig ikke noget hurtigere end C++

Tips og korrekturforslag til denne historie sendes til tip@version2.dk
Kommentarer (23)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Bo Lorentsen

Jeg vil på bedste udansk maner udtrykke min store begejstring og taknemmelighed, for denne rigtig lækre konsolidering af C++11, som i forvejen er en rigtig nyttig udvidelse af mit gamle ynglings sprog.

Især vil jeg gerne henlede opmærksomhedden på lambda (sammen med tubles og function), som nok er noget af det bedste jeg kunne ønske mig. Endeligt et sprog hvor man faktisk kan se og forstå prisen (og livs forløbet) ved at bruge disse. Ikke nogen sær GC ikke nogen skjult omkostning, helt som det var i starten af C++'s dage.

Tænk at vi stadig har sprog det smukt sammenføjer fuld kontrol med stærk struktur, hvor OO kode og functionel kode kan gå hånd i hand. Og ingen GC der står i vejen i tide og utide ...

Så tak for et fantastisk værktøj, keep it comming :-)

  • 8
  • 0
Finn Ellebæk Nielsen

100% enig. Specielt ifm. C++-klasser der giver adgang til kritiske ressourcer. Det er barneleg at sikre at disse bliver frigivet på det rette tidspunkt, fordi man som programmør blot frigiver disse i klassens destructor, som enten automatisk bliver kaldt når instansen går ud af scope eller kaldes manuelt.

Dette er efter min mening én af de største mangler ved Java.

  • 2
  • 0
Michael Aggerholm

Det er bad practice at lægge kode på en destructor, da man risikerer at binde ressourcer længere tid end nødvendigt (potentielt set uendeligt) da man ikke har nogen garanti for at koden nogensinde bliver kaldt, eller hvornår det sker. Desuden aner destructoren ikke hvor meget af koden i objektet der er udført, så det må den først undersøge før den ved hvad der skal frigives. Potentialet for fejl er stor.

Jeg kan ikke forstå din udtalelse om at java har en mangel her. Java frigiver via GC de ressourcer der måtte være allokerede.

Og det der med manuelt at kalde en destructor, det er så typisk en C++ tankegang at man må trække lidt på smilebåndet. Tænk at man ligefrem efterspørger mere boilerplate kode.

  • 2
  • 4
Troels Henriksen

Det er bad practice at lægge kode på en destructor, da man risikerer at binde ressourcer længere tid end nødvendigt (potentielt set uendeligt) da man ikke har nogen garanti for at koden nogensinde bliver kaldt, eller hvornår det sker. Desuden aner destructoren ikke hvor meget af koden i objektet der er udført, så det må den først undersøge før den ved hvad der skal frigives. Potentialet for fejl er stor.

Det, du her siger, gælder for finalizere i Java (og andre GC-sprog). C++-destructorer er helt deterministiske: De afvikles når objektet destrueres, hvilket sker når det går ud af scope, eller der bliver kaldt 'delete' på det (afhængigt af hvorvidt allokeringen er automatisk eller manuel).

Denne deterministiske, men dog strukturerede, resursestyring er en af de få ting i C++ jeg selv synes fungerer bedre end man ser i de fleste andre sprog (omend de fleste har 'using'-blokke eller lignende der gør nogenlunde det samme).

  • 7
  • 0
Finn Ellebæk Nielsen

Jeg er uenig i dine betragtninger Michael. Det er netop good practice at lukke kritiske ressourcer brugt af objektet i destructor'en, da man er sikret at den bliver kaldt på det rette tidspunkt - når objektet ikke længere skal bruges. Ethvert objekt bør kende sin tilstand, så baseret på denne er det uproblematisk at finde frem til hvad der skal frigives. Hvis objektet skal bruge en kritisk ressource i hele dets levetid skal denne frigives netop når objektet ikke længere skal bruges, dvs. i destructor'en.

Som Troels skriver er det helt deterministisk og det er netop problemet med Java og GC - man kan ikke være sikker på at et objekt bliver frigivet overhovedet hvis der er masser af hukommelse til rådighed. Det er derfor at man så bliver nødt til at belemre brugeren af et objekt med overflødige metodekald som close() på en OutputStream, hvor dette tilsvarende i C++ kunne ske i en destructor der automatisk ville blive kaldt, når objektet forlader scope (f.eks. en lokalvariabel) eller manuelt slettet vha. delete. Så Java kræver at brugeren af objektet opfører sig korrekt og foretager manuelle kald på det rigtige tidspunkt og det giver for at bruge din terminologi netop mere boilerplate kode og samtidig er potentialet for fejl stor.

Min kommentar om at kalde destructor'en manuelt var vist ikke helt godt forklaret - jeg mente at nedlukke objektet ved at kalde delete.

  • 3
  • 0
Lasse Lasse

Det er bad practice at lægge kode på en destructor, da man risikerer at binde ressourcer længere tid end nødvendigt

Det er nok mere bad practise fordi koden i destructoren jo kunne kaste en exception, hvilket er uigennemskueligt kompliceret (i C++11 er destructors blevet noexcept pr default og dit program vil terminere).

  • 0
  • 0
Bjørn Reese

Det er bad practice at lægge kode på en destructor, da man risikerer at binde ressourcer længere tid end nødvendigt (potentielt set uendeligt) da man ikke har nogen garanti for at koden nogensinde bliver kaldt, eller hvornår det sker.

Hvis man ikke må have kode i destructor, hvorfor så have en destructor?

Mht. garantier, så er du garanteret at destructor bliver kaldt når objektet dør. Dvs. når et lokalt objekt går ud af scope, eller når et allokeret objekt frigives. Jeg tror du tænker på en praksis fra 1990'erne hvor man brugte new direkte, og glemte at kalde delete. I C++11 er det ikke længere nødvendigt, idet det anbefales at man bruger smart pointere, som er et deterministisk alternativ til garbage collection.

Desuden aner destructoren ikke hvor meget af koden i objektet der er udført, så det må den først undersøge før den ved hvad der skal frigives. Potentialet for fejl er stor.

Destructor ved at constructor er udført. Den generelle anbefaling er at en klasse har ansvaret for en resource, hvorved resourcestyring bliver triviel. Hvis du har brug for to resourcer i en klasse, så kan du lave en RAII klasse til hver, og bruge disse i din klasse.

  • 3
  • 0
Mogens Hansen

Det er bad practice at lægge kode på en destructor, da man risikerer at binde ressourcer længere tid end nødvendigt (potentielt set uendeligt) da man ikke har nogen garanti for at koden nogensinde bliver kaldt, eller hvornår det sker. Desuden aner destructoren ikke hvor meget af koden i objektet der er udført, så det må den først undersøge før den ved hvad der skal frigives. Potentialet for fejl er stor.

Som andre har været inde på er den holdning helt forkert i relation til C++.
For mig lyder det som en beskrivelse af finalize i Java

Jeg kan ikke forstå din udtalelse om at java har en mangel her. Java frigiver via GC de ressourcer der måtte være allokerede.

Java frigiver hukommelse via GC - ikke resourcer (som f.eks. åbne filer) generelt.

Og det der med manuelt at kalde en destructor, det er så typisk en C++ tankegang at man må trække lidt på smilebåndet. Tænk at man ligefrem efterspørger mere boilerplate kode.

Beklager - men det er mit klare indtryk at du har ringe kendskab til C++.
Man kan kalde en destructor explicit (typisk i sammenhæng med placement new) - men det er yderst sjældent at man gør det.
Pointen med destructorer i C++ er netop at de bliver udført automatisk og deterministisk - så der er ikke noget boilderplate.

Bemærk at der i C++ er en væsentlig skelnen mellem destructor og operator delete (som frigiver hukommelse) - det giver nemt anledning til at man taler forbi hinanden hvis man ikke gør sig det klart.

  • 2
  • 0
Niels Dybdahl

Det er derfor at man så bliver nødt til at belemre brugeren af et objekt med overflødige metodekald som close() på en OutputStream,

I Java 7 kan et object som implementerer AutoCloseable puttes i en try block og så bliver close() automatisk kaldt, når referencen går ud af scope.
Dette ligner meget destructorer i C++ men med en afgørende forskel:
Hvis programmet er igang med at håndtere en exception og derfor kalder en destructor/close(), så må destructoren (C++) ikke selv kaste exceptions. Hvis den gør, så lukker programmet bare ned. Close() må godt kaste en exception, som så bliver ignoreret.
Det er frygteligt bøvlet i de C++ versioner jeg kender at håndtere dette korrekt, mens det i Java7 er ligeud af landevejen. Har de gjort noget ved det problem i C++11 eller C++14?

  • 0
  • 0
Sune Marcher

I Java 7 kan et object som implementerer AutoCloseable puttes i en try block og så bliver close() automatisk kaldt, når referencen går ud af scope.


...og så har du stadig overflødigt boilerplate.

Hvis programmet er igang med at håndtere en exception og derfor kalder en destructor/close(), så må destructoren (C++) ikke selv kaste exceptions.


Indeed.

Det er dårlig stil at kaste exceptions i destructors. Hvis du har en velskreven klasse der bruger objekter af knap-så-velskrevne klasser, har du to valg:
1) "right, vi kan leve med den her exception": opsug exception og smid en warning-log.
2) crash and burn. Hvis din program-state muligvis er kompromiteret, er dette det rigtige at gøre.

C++ kan, fornuftigt, håndtere deallokering af ikke-memory resourcer - det kan Java, C# osv. ikke. Ja, det kræver lidt mere omtanke generelt (muligvis brug af shared_ptr, unique_ptr, osv), men i det store hele synes jeg oftere jeg i Java er nødt til manuelt at kalde dispose/close-metoder end jeg i C++ er nødt til at tage stilling til pointer ownership rules.

  • 0
  • 0
Troels Henriksen

Har i hørt om "loan pattern"?

Det kræver en del mere boilerplate. Både i brugen, som du selv illustrerer, og sikkert også i implementeringen. Så er det noget nemmere blot at definere passende constructorer og destructorer, som i C++.

Endvidere er dit eksempel faktisk mindre fleksibelt, end man kunne gøre det i C++, idet dit fil-objekt kun eksisterer inden i den givne kodeblok. I C++ kunne du returnere et sådan fil-objekt fra en funktion, og via brug af referencetælling og en copy-constructor sikre, at filen vil være åben indtil objektet reelt ikke eksisterer længere. Denne metode er naturligvis sårbar overfor hukommelseslækager, omend moderne C++ har faciliteter der gør den slags mindre sandsynligt.

  • 1
  • 0
Niels Dybdahl

Det er dårlig stil at kaste exceptions i destructors.

Det er det i C++, men ikke længere i Java (altså i AutoCloseable.close()) af de ovennævnte årsager.
Så i C++ er man ofte nødt til at lave en ekstra close() funktion som kan kaste en exception og som man så kalder til sidst inden objektet går ud af scope.
F.eks hvis man skriver til en fil og til sidst vil lukke den, så kan der jo komme en fejl når bufferne bliver flushet etc under lukningen. Og det kan man håndtere med et implicit kald i Java7 (dvs uden boilerplate) men kun med et explicit kald i C++ (dvs med boilerplate).

  • 0
  • 0
Baldur Norddahl

Det kræver en del mere boilerplate. Både i brugen, som du selv illustrerer, og sikkert også i implementeringen. Så er det noget nemmere blot at definere passende constructorer og destructorer, som i C++.

Boilerplate? Det er praktisk taget en one-liner!

Alle sprog er forskellige og der er da fordele ved dekonstruktører. Men fordelen svinder ind når du har værktøjer som loan-pattern, som effektivt giver præcis det samme når det gælder ressource styring. GC giver på den anden side også fordele - kan du overhovedet anerkende det?

Endvidere er dit eksempel faktisk mindre fleksibelt, end man kunne gøre det i C++, idet dit fil-objekt kun eksisterer inden i den givne kodeblok. I C++ kunne du returnere et sådan fil-objekt fra en funktion, og via brug af referencetælling og en copy-constructor sikre, at filen vil være åben indtil objektet reelt ikke eksisterer længere. Denne metode er naturligvis sårbar overfor hukommelseslækager, omend moderne C++ har faciliteter der gør den slags mindre sandsynligt.

Så snart du gør det har du ikke længere den fuldkomne sikkerhed for at ressourcen frigives. Du er ikke bedre stillet end old-school java.

Jeg må stille mig lidt undrende overfor denne fokusering på et non-problem. Ressource-lækager er ikke noget jeg har måtte kæmpe meget med i min karriere. Når de forekommer, så er de ikke så svære at debugge og lukke. Dårlige pointere derimod - det er et mareridt.

  • 1
  • 0
Troels Henriksen

Boilerplate? Det er praktisk taget en one-liner!

Til gengæld kræver det et indenteringsniveau for hvert objekt. Jeg synes C++'s brug af almindelig variabelerklæringssyntaks er noget mere elegant i den henseende.

Boilerplate? Det er praktisk taget en one-liner!

Alle sprog er forskellige og der er da fordele ved dekonstruktører. Men fordelen svinder ind når du har værktøjer som loan-pattern, som effektivt giver præcis det samme når det gælder ressource styring. GC giver på den anden side også fordele - kan du overhovedet anerkende det?

Jeg kan ikke udstå C++ og bruger det aldrig i mit daglige liv (mit arbejde er mest Haskell og C), så hvorfor tror du ikke jeg forstår fordelene ved GC? Jeg synes bare ikke, at en GC's fordele bliver fremhævet særligt godt af de fleste af fortalerene - f.eks. påpeges det aldrig, at referencetælling kan have store ydelsesmæssige konsekvenser når der skal frigøres store objektgrafer, idet man skal vandre langs hele grafen.

Så snart du gør det har du ikke længere den fuldkomne sikkerhed for at ressourcen frigives. Du er ikke bedre stillet end old-school java.

Næh, men på det punkt hvor C++ normalt bruges, der har man alligevel opgivet den perfekte sikkerhed. Det er også noget jeg som regel selv finder frustrerende, for C++ lægger meget op til at man bygger abstraktioner, men slige abstraktioner er ofte ret hullede. Man må bare erkende, at kontrol har visse omkostninger.

Dårlige pointere derimod - det er et mareridt.

Moderne C++ har rigeligt med faciliteter til at undgå disse, og selv i C er lidt disciplin nok til at nå langt af vejen. Især bliver ens liv meget nemmere, hvis man accepterer at tage nogle flere kopier, i stedet for at have en fuglerede af overlappende pegere til de samme data.

  • 0
  • 0
Baldur Norddahl

Til gengæld kræver det et indenteringsniveau for hvert objekt. Jeg synes C++'s brug af almindelig variabelerklæringssyntaks er noget mere elegant i den henseende.

Det er bare en mekanisk omskrivning af koden. Det vil ikke undre om nogen en dag laver en Scala-makro der gør det automatisk.

Jeg synes bare ikke, at en GC's fordele bliver fremhævet særligt godt af de fleste af fortalerene

Velsagtens fordi det ikke er emnet i denne tråd. Vi har haft tidligere tråde om GC hvor jeg synes den slags er blevet sagt mange gange. Senest under artiklen om Swift og Apples valg af ARC.

Moderne C++ har rigeligt med faciliteter til at undgå disse, og selv i C er lidt disciplin nok til at nå langt af vejen.

Jo, men det svarer til at i Java er ressource-leaks hellere ikke en mulighed, hvis blot programmørerne har den mindste disciplin og bruger try-finally til at frigive ressourcer. Og det har de fleste vel efterhånden lært, så derfor er det bare ikke et reelt problem.

Javas try-finally fylder bare en del kode at skrive, men det er man vandt til i Java lejren :-). Man lader IDE'en skrive boilerplatte og så er man glad.

Hvis jeg skulle designe et sprog, så blev det uden dekonstruktører. De er nyttige men de sætter også nogle begrænsninger i hvordan du kan implementere sproget. Den primære use-case der bliver fremhævet er ressource styring, og det problem er bare ikke særligt stort.

  • 0
  • 0
Nikolaj Brinch Jørgensen

At lave destructorbaseret ressourcestyring, er det en god idé.

Når nu der sprøjter exceptions ud herfra, begynder det at blive vanskeligt og noget rod.

Ressourcestyring bør (IMO) foretages præcist og eksplicit.

Destructors er generelt ikke nødvendige. Derfor blev de da også aflivet da Java blev konstrueret. I C++ er de en integral del og kan ikke uden videre fjernes. Blev sproget designet i dag, ville de også blive fjernet. Destructors er dog den første mangel C++-programmøren ser i Java når han (mig selv inklusive) stifter bekendtskab med Java. Men det er kun indtil man forstår modellen.

Det er rigtigt at GC har den dårligdom, at den lokker en del til at tro at memory management ikke er noget man behøver at bekymre sig om på en platform som benytter dette.

Hvis man i f.eks. Java ønsker sig destructors kan man lave det med AOP - no sweat. Et bedre alternativ til diskussionen om ressourcestyring er 'try with resources'.
Man kan også indføre ARC i Java med AOP, som f.eks. Obj-C og Swift har det.

  • 0
  • 1
Nikolaj Brinch Jørgensen

Har du belæg for den udtalelse? Når jeg har set C++-designere snakke om hvad de ville fjerne hvis de kunne, så nævner de ikke destructorer.


Nej det har jeg ikke, og det er ved nærmere tanke heller ikke sikker på de ville :-).

Men sammenligningen mellem Java og C++ er også lidt svær, da domænerne de retter sig imod ikke længere er gode at sammenligne.

  • 0
  • 0
Log ind eller Opret konto for at kommentere