Főoldal

"Mérnököt a mérnöktől"

A Schönherz Bázis összeköti az állást kereső és állást kínáló mérnököket.

CV küldés

Küldj önéletrajzot! Gyorsan, egyszerűen.
Megjegyzésbe írd be a pozíció nevét.
CV küldés

Iratkozz fel hírlevelünkre!

Hírek

A C++ legnépszerűbb mítoszai III. rész
A C++ legnépszerűbb mítoszai III. rész
A cikksorozat első részét itt, a másodikat pedig itt találod

Bevezetés
 
A cikksorozattal az az elsődleges célom, hogy bemutassam az 5 leggyakoribb mítoszt, ami a C++-t övezi. A sorozat mostani, befejező része két gyakran előforduló mítosszal foglalkozik. Először kifejtem miért hívom őket mítosznak. Az első állítás szerint a hatékony kódnak low level-nek kell lennie. A második városi legenda szerint pedig C++-ban csak óriási kódot érdemes írni.
Ezek a legendák is leginkább arra jók, hogy feleslegesen elrettentsék a felhasználókat a C++-tól. 
 
Íme öt pontos listánk negyedik állomása:
 
4. Mítosz: A hatékonysághoz alacsony szinten kell kódolni
 
Rengeteg ember hiszi, hogy a hatékony programok minden egyes részét a programozó készítette, kifejezetten az adott probléma megoldására. Tehát sokakban él az a tévhit, hogy a alacsony szintű programozás az egyetlen módja a hatékony kódot készítésének. Sőt, ami még ennél is rosszabb, hogy sokan úgy vélik, az alacsony szintű kód már önmagában is garancia a hatékonyságra.
Gyakran hallom az alábbi érvelést: “Ez nagyon rusnya, ha valami ilyen bonyolult, akkor az tuti gyors, hiszen valaki rengeteg időt töltött el vele, így biztos hatékonynak kell lennie.”
 
Természetesen lehetséges csak és kizárólag alacsony szintű kódot használni, és ez még nem is jelenti feltétlenül azt, hogy tuti nem lesz jó. Érdemes azonban mérlegelni: tényleg megéri a befektetett munkát? A modern architektúrák trükkösek, ezzel szemben a mai C++ fordítók meg hatékonyak. Az alacsony szintű kódokat tipikusan egy-egy interfész mögött találjuk, így kényelmesebb a program használata, és könnyebb optimalizálni is.
 
4.1 : qsort() C vs C++
Következzen egy kis összehasonlítás, hogyan is működik a qsort() C-ben? És C++-ban?
 
Nézzük először a C-t, egy egyszerű példán keresztül. Tegyük fel, hogy csökkenő sorrendbe akarsz rendezni egy adag lebegőpontos számot. Erre akár írhatsz is egy kódot, csak általában nem érdemes.
 
Nézzük, hogy működne ez C-ben a standard ISO C könyvtárral:
 
 
int greater(const void* p, const void* q) // three-way compare

{

double x = *(double*)p; // get the double value stored at the address p

double y = *(double*)q;

if (x>y) return 1;

if (x<y) return -1;

return 0;

}

void do_my_sort(double* p, unsigned int n)

{

qsort(p,n,sizeof(*p),greater);

}

int main()

{

double a[500000];

// ... fill a ...

do_my_sort(a,sizeof(a)/sizeof(*a));

// ...

}

 
Nézzük ezt meg közelebbről! Mit veszünk észre? Nos, az interfész eldobálja az információt, nem byteokat szortírozunk, hanem double-okat, de ezt a qsort nem tudja, így valamilyen módon meg kell adnunk ezt az információt a számítógépnek. Itt megjegyezném, hogy a fordító ezt mind pontosan tudja. Magától.
Csakhogy az interfész nem engedi szegényt szóhoz jutni, magyarul: írtunk egy alacsony szintű kódot, ami bonyolult és még csak nem is igazán hatékony.
 
Nézzük meg a példát C++-ban:
 
void do_my_sort(vector<double>& v)

{

sort(v,[](double x, double y) { return x>y; });

}

// sort v in decreasing order

int main()

{

vector<double> vd;

// ... fill vd ...

do_my_sort(v);

// ...

}

 
Ez eléggé egyértelmű, nem szorul sok magyarázatra.  A vektor tudja a saját méretét, így semmi szükség arra, hogy expliciten átadjuk az elemek számát. Nem vesztünk információt, nem vesztjük el az elemeket, így nem is kell a vektor méretével később foglalkoznunk. A sort alapesetben növekvő sorrendbe teszi a számokat, így ebbe kicsit bele kell nyúlni, de ezt meg kellett tennem a C verziónál is. Itt most lamda kifejezéssel oldottam meg, két double-t hasonlítottam össze. Még tovább is mehetnénk, és írhatnám a következőt:
 
sort(v,greater<>());

Mi az ítélet? Melyik a gyorsabb?  Mindkettő fordul különösebb teljesítmény probléma nélkül, így bármelyik jó lehet, programozási stílus kérdése. De semmiképp sem rosszabb vagy nehezebb a C++  verzió! Ez remélem látszik.


 
Lefuttattam őket, és a sort 2,5-szer gyorsabb volt. Persze a futási idő sok mindentől függ, géptől, fordítótól, az adott esetben használ könyvtáraktól, de én nem találtam olyan körülményt, amely mellett a qsort gyorsabb lett volna.

 
5. Mítosz: A C++ csak nagy, bonyolult programok írására jó
A C++ egy összetett nyelv, a definíciók mérete nagyjából megegyezik a C#-éval. Na de ez nem jelenti azt, hogy nekünk ezt mind tudnunk is kell. Itt egy végtelenül egyszerű kis példa, amely csak a standard könyvtárt használja:
 
set<string> get_addresses(istream& is)

{

set<string> addr;

regex pat { R"((\w+([.-]\w+)*)@(\w+([.-]\w+)*))"};

smatch m;

for (string s; getline(is,s); )

if (regex_search(s, m, pat))

addr.insert(m[0]);

return addr;

}


  
Feltételezem a reguláris kifejezéseket nem kell bemutatnom senkinek. A példában a move sematikára építek, így hatékonyan kaphatok vissza nagy méretű stringeket. Ahhoz hogy ez működjön kell még pár dolog:
 
#include<string>

#include<set>

#include<iostream>

#include<sstream>

#include<regex>

using namespace std;

 
 
Most már összeállt a kép, teszteljük:
 
istringstream test {

 
"asasasa\n"

"bs@foo.com\n"

"ms@foo.bar.com$aaa\n"

"ms@foo.bar.com aaa\n"

"asdf bs.ms@x\n"

"$$bs.ms@x$$goo\n"

"cft foo-bar.ff@ss-tt.vv@yy asas"

"qwert\n"

int main()

{

auto addr = get_addresses(test);

for (auto& s : addr)

cout << s << '\n';

}

 
Ez csak egy példa, könnyű módosítani, hogy pl. URL-t találhassak meg. Az sem túl bonyolult, hogy a get_adresses()-t módosítsa ne csak egy mintát találjon meg. Hiszen ahogy látjuk, a C++ valóban az általánosságra és a rugalmasságra törekszik, de ez nem jelenti azt, hogy csak olyan programot írhatok, ami aztán minden könyvtárat használ. És ezzel el is érkeztünk mítoszunk egy fontos pontjához, a könyvtárakhoz.


 
5.2 Mítosz: Könyvtárak
 
Nem számít, milyen nyelven programozunk, ha csak a beépített funkciókat használjuk (pl for, if, +), akkor elég sok problémánk lesz, és bele fogunk őrülni az unalomba. Ha viszont vannak megfelelő könyvtáraink, szinte semmi sem lehetetlen. Az ISO C++ standard könyvtára elég kicsi, de rengeteg  nyílt forráskódú könyvtár van. Pl. a Boost, a POCO az AMP, a TBB használatával rendkívül sokrétű problémaköröket is kezelhetünk.
Módosítsuk a fenti példát! Most azt szeretném elérni, hogy URL címeket olvasson weblapról. Ehhez először is általánosítani kell a get_addresses()-t, hogy képes legyen megtalálni a mintákat.
 
 set<string> get_strings(istream& is, regex pat)

{

set<string> res;

smatch m;

for (string s; getline(is,s); )

// read a line

if (regex_search(s, m, pat))

res.insert(m[0]);

// save match in set

return res;

}


 
Most arra kell rájönnünk, hogyan olvasunk fájlból a weben. A Boost rendelkezik egy könyvtárral, ami lehetővé teszi a kommunikációt a weben.
 
#include “boost/asio.hpp”

int main()

try {

string server = "www.stroustrup.com";

boost::asio::ip::tcp::iostream s {server,"http"}; // make a connection

connect_to_file(s,server,"C++.html");

regex pat {R"((http://)?www([./#\+-]\w*)+)"}; // URL

for (auto x : get_strings(s,pat))


cout << x << '\n';

}

catch (std::exception& e) {

std::cout << "Exception: " << e.what() << "\n";

return 1;

}


 
Pl. a  www.stroustrup.com’s  C++.html fájlján futtatva a következőket kapjuk:

http://www-h.eng.cam.ac.uk/help/tpl/languages/C++.html

http://www.accu.org

http://www.artima.co/cppsource

http://www.boost.org


 
Hello World!
A C++ elsődleges célja, hogy akkor is kezelhető kódot tudjunk írni, ha lényeges, hogy a program hogyan kezeli a rendelkezésre álló forrásokat. Így persze, ha valami nagyon apró dolgot írunk, akkor sosem lesz olyan hatékony mint pl. a Javascript. Azonban rengeteg olyan hasznos C++ program van, ami mindössze néhány száz soros. Utolsó példánk legyen a létező legegyszerűbb dolog. Ez mindennek a kezdete, ha valaki programozni tanul: a hello world.
 
#include<iostream>

int main()

{

std::cout << "Hello, World\n";

}


 
 
Összefoglaló
Ezzel háromrészes cikksorozatunk végére is értünk. Az utolsó részben megpróbáltam rávilágítani 2 újabb mítosz hiteltelenségére. Igenis lehet néhány száz soros C++ kódot írni, a nagyon apró dolgokra ott vannak más nyelvek, ezt nem tagadom, de egy ilyen állítással olyanokat is távol tarthatunk a C++-tól, akiknek pont erre lenne szükségük.
 
Végezetül öt pontban összefoglalnám milyen mítoszok ellen is “kampányoltam” ebben a cikksorozatban, és mik a végkövetkeztetéseim.

1. Először is, ne tanulj C-t a C++ előtt! A mai modern fordítókkal sokkal egyszerűbb C++-al kezdeni, főleg ha kezdő programozó vagy.
 
2. A C++ sokkal több, mint egy objektumorientált nyelv! Inkább általánosnak mondanám.

3. Felejtsd el a Garbage Collection-t, de legalábbis ne ez legyen az első ötleted.

4. Alacsony szintű kódot használni csak akkor érdemes, ha tényleg valami speciálisat csinálsz, amúgy szinte biztos, hogy a már kész kód is megteszi.

5. Ne gondold, hogy csak óriási méretű kódokhoz érdemes C++-t használni.
 
Az egész cikksorozattal az volt a célom, hogy bemutassam a programozás terén sem szabad elhinni minden mendemondát. Az öt mítosz sok esetben megalapozottnak tűnhet, de ez inkább csak régen volt igaz.



 Az új, modern C++-t használva nagyon kevés olyan esetet tudok elképzelni, mikor ezeknek van létjogosultsága. Az igazság az, hogy cikkben felsorolt városi legendák terjesztői leginkább saját lustaságuk, és változtatni nem akarásuk miatt riasztanak el leendő programozókat a C++-tól.
 
Az üzenetem tehát az, hogy bátran programozz C++-ban!
 
Írta: Bjarne Stroustrup
 
(Forrás)