Clasicul si modernul C++ - cine e interesat?
#163
Posted 17 April 2019 - 12:36
TS030, on 17 aprilie 2019 - 12:26, said:
Engine-ul Id Tech 4, folosit pentru Doom 3, a fost scris in C++! Parabellum spune ca C++ folosit corect are zero overhead. C++, fata de C, poate chiar avea un avantaj in ceea ce priveste performanta! Exemplul clasic este cel al functiei sort(), vs. qsort din C: https://www.geeksfor...sort-vs-c-sort/ Templates vs. void*. |
#164
Posted 17 April 2019 - 12:52
TS030, on 16 aprilie 2019 - 13:05, said:
set de reguli de bun simt din care majoritatea intuitive, usor de explicat si de aplica ca de exemplu de ce acest cod este corect: int a[2]; a[4] = 5; cout << a[4]; nu primesti nici macar un warning de la compilator... sau ... cum se citesc: int const const *p int const *const p const int const *p int const ** const p sau.... ce avem aici: int *(*(*i)())[5] gasesti o multime de intrebari pe stackoverflow legate de citirea declaratiilor ce implica pointeri, pentru ca, nu-i asa, reguli de bun simt din care majoritatea intuitive, usor de explicat Si vorbim de chestii elementare. TS030, on 14 aprilie 2019 - 17:39, said:
cout << "Please enter your name:"; string name; getline(cin, name); cout << "Hello, " + name << "\n"; Utilizarea corecta(scrisa de orice programator cat de cat experimentat) ar fi: cout << "Hello, " << name << "\n"; Dar ce se intampla daca name este schimbat cu o variabila de tip int sau char si pastram acel "+"? sa zicem: int age; cin >> age; cout << "Your age is:" + age; Surprize, surprize. Pentru ca ... reguli de bun simt din care majoritatea intuitive, usor de explicat si de aplicat Un exemplu care demonstreaza faptul ca operator overloading nu e o idee buna. TS030, on 14 aprilie 2019 - 17:39, said:
Iata un alt exemplu simplu (si incorect, poate ceva ce-ar scrie un programator Java): int main() { int* a = new(int); }Obtin 3 warning-uri: 2. Nu, acesta este genul de cod pe care nu prea ar avea cum sa-l scrie un programator java, pentru ca nu i-ar trece prin minte ca operatorul new poate lua argumente, si mai mult decat atat, ca ar lua ca argument un tip de date primitiv si atat. Acesta este cod scris de cineva neexprimentat si care a gasit pe undeva pe internet acest idiom neobisnuit. Idiomul obisnuit este: int* a = new int; asta se numeste "default-initialized" object (care de fapt e uninitialized in cazul int) bonus, mai avem: int* a = new int(); int* a = new int{}; care sunt value-initialized objects (cazul int, zero-initialized) ... pentru ca ... reguli de bun simt din care majoritatea intuitive, usor de explicat si nici n-am ajuns la new[] & co, sau placement new; 3. warningurile nu au neaparat relevanta - se bazeaza pe diverse recomandari(nicidecum nu fac parte din standard) si variaza de la compilator la compilator. spre exemplu compilatorul de la gcc(g++) nu da absolut niciun warning pentru acel cod Edited by adamsd, 17 April 2019 - 12:55. |
#165
Posted 17 April 2019 - 12:52
Quote
cel mai probabil s-au folosit versiuni diferite de implementare a algoritmului (exemplu de ce contine MKL: https://en.wikipedia.org/wiki/LAPACK ). Metodele alea sunt foarte dificil daca nu imposibil de implementat la modul realist, in C. Quote
Un exemplu care demonstreaza faptul ca operator overloading nu e o idee buna. MatrixA.plus(MatrixB.minus(MatrixC.multipliedby(MatrixD))) Chestia asta la formule mai complicate incepe sa devina iad. Edited by parabellum, 17 April 2019 - 12:57. |
#166
Posted 17 April 2019 - 13:26
adamsd, on 17 aprilie 2019 - 12:52, said:
"foarte"! ca de exemplu de ce acest cod este corect: int a[2]; a[4] = 5; cout << a[4]; nu primesti nici macar un warning de la compilator... Codul respectiv nu este corect; este undefined behavior. Am citat ieri-alaltaieri din standard, ca sa stiti si voi ca un diagnostic la compilare nu este obligatoriu. O analiza statica de cod - fie si cea din VS - va prinde chiar cazuri mai complicate. warning C6201: Index '4' is out of valid index range '0' to '1' for possibly stack allocated buffer 'a'. warning C6201: Index '4' is out of valid index range '0' to '1' for possibly stack allocated buffer 'a'. warning C6385: Reading invalid data from 'a': the readable size is '8' bytes, but '20' bytes may be read. warning C6386: Buffer overrun while writing to 'a': the writable size is '8' bytes, but '20' bytes might be written. warning C26483: Value 4 is outside the bounds (0, 1) of variable 'a'. Only index into arrays using constant expressions that are within bounds of the array (bounds.2). warning C26483: Value 4 is outside the bounds (0, 1) of variable 'a'. Only index into arrays using constant expressions that are within bounds of the array (bounds.2). Apoi, codul asta este C cu cout, nu C++. adamsd, on 17 aprilie 2019 - 12:52, said:
gasesti o multime de intrebari pe stackoverflow legate de citirea declaratiilor ce implica pointeri, pentru ca, nu-i asa, reguli de bun simt din care majoritatea intuitive, usor de explicat Si vorbim de chestii elementare. In C te lovesti de pointeri de la inceput. In C++... cartea lui Stroustrup, "Programming: Principles and Practice using C++" te baga serios in pointeri in capitolul 17. C++ are o serie de mecanisme pentru a evita asemenea complicatenii. lambda vs function pointer? adamsd, on 17 aprilie 2019 - 12:52, said: Aceasta concatenare de stringuri este ineficienta si anacronica in contextul utilizarii streamurilor. Utilizarea corecta(scrisa de orice programator cat de cat experimentat) ar fi: cout << "Hello, " << name << "\n"; printf("Hello, %s\n", name);? adamsd, on 17 aprilie 2019 - 12:52, said:
Dar ce se intampla daca name este schimbat cu o variabila de tip int sau char si pastram acel "+"? sa zicem: int age; cin >> age; cout << "Your age is:" + age;Surprize, surprize. Pentru ca ... reguli de bun simt din care majoritatea intuitive, usor de explicat si de aplicat Un exemplu care demonstreaza faptul ca operator overloading nu e o idee buna. Ce am demonstrat eu e concatenarea a doua string-uri, nu stream-urile. Un amarat de + in C++, iar in C ce ni s-a oferit? Un crash, apoi un buffer overflow, apoi un stack overflow... Ce semantica ar avea concatenarea unui int cu un string? Adaugi un numar, reprezentat in baza 10, la un string? Sau poate string-ul reprezinta un numar si trebuie sa-l convertesti la integer? This is C++! - not Javascript. adamsd, on 17 aprilie 2019 - 12:52, said: 1. Exemplul este corect. - nu exista nici un motiv pentru a aloca a (un amarat de int) dinamic - a nu este dealocat - int *a este owning pointer, si se foloseste naked new - cand ai ownership folosesti un smart pointer (unique_ptr by default) Astea chiar sunt reguli simple, usor de inteles si aplicat! adamsd, on 17 aprilie 2019 - 12:52, said: 2. Nu, acesta este genul de cod pe care nu prea ar avea cum sa-l scrie un programator java Apoi, dupa ce te scremi sa-mi dai in cap pentru acel detaliu, te bati pe umar ca ai fost baiat fain si n-ai vorbit de placement new... bravos! adamsd, on 17 aprilie 2019 - 12:52, said:
3. warningurile nu au neaparat relevanta - se bazeaza pe diverse recomandari(nicidecum nu fac parte din standard) si variaza de la compilator la compilator. spre exemplu compilatorul de la gcc(g++) nu da absolut niciun warning pentru acel cod Doar pe la liceu iti permiti sa le ignori. Si iata cum se duce naibii topicul. Edited by TS030, 17 April 2019 - 13:28. |
#167
Posted 17 April 2019 - 13:57
Ba, deci pana la urma cine bate? Batman sau Superman, Terminator sau Predator, Mercedes sau BMW?
|
#168
Posted 17 April 2019 - 14:03
parabellum, on 17 aprilie 2019 - 12:52, said: MatrixA.plus(MatrixB.minus(MatrixC.multipliedby(MatrixD))) Chestia asta la formule mai complicate incepe sa devina iad. Eu de exemplu pe "1" + "2" l-as defini ca: aduna doua numere salvate ca stringuri, returneaza suma, sau arunca o exceptie daca acolo nu sunt numere. |
#169
Posted 17 April 2019 - 14:26
#170
Posted 17 April 2019 - 15:08
#171
Posted 17 April 2019 - 15:17
#172
Posted 17 April 2019 - 15:20
De fapt, daca vrei sa aduni doua numere asa, ai
std::stoi, de exemplu. '+' e folosit pentru concatenare stringuri si in alte limbaje (java, javascript, C#, python). E o chestiune de preferinte sa ai sau nu overloading pe el pentru stringuri, din motive de lene eu prefer + in loc de 'gen a.append(b)'. Plus ca e mai inteligibil codul. |
|
#173
Posted 17 April 2019 - 15:43
Mai este inca un aspect: a + b are mai mult sens decat a.append(b) pentru ca rezultatul... nu este a la care ai concatenat b! Este un obiect independent.
a.append(b) este semantic echivalent cu a+=b, nu cu a+b. O concatenare corecta de string-uri este ca in C++, unde operator+ nu e o functie membru. IMHO Ca parabellum a mentionat Java: acolo folosesti + sa concatenezi doua stringuri, dar... equals ca sa le compari! Asta e inconsistent. Javascript... nici nu mai vorbesc ce bazaconii se intampla acolo. Edited by TS030, 17 April 2019 - 15:37. |
#174
Posted 17 April 2019 - 17:40
TS030, on 17 aprilie 2019 - 13:26, said:
A tunat si v-a adunat! Codul respectiv nu este corect; este undefined behavior. Am citat ieri-alaltaieri din standard, ca sa stiti si voi ca un diagnostic la compilare nu este obligatoriu. [..] Apoi, codul asta este C cu cout, nu C++. Din nou, vorbesti de C. In C te lovesti de pointeri de la inceput. In C++... cartea lui Stroustrup, "Programming: Principles and Practice using C++" te baga serios in pointeri in capitolul 17. Quote
3.27 [defns.undefined] undefined behavior behavior for which this document imposes no requirements Undefined behavior may be expected when this document omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression never exhibits behavior explicitly specified as undefined (8.6). 11.3.1 Pointers [dcl.ptr] 1 In a declaration T D where D has the form * attribute-specifier-seqopt cv-qualifier-seqopt D1 and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is “derived-declarator-type-list cv-qualifier-seq pointer to T”. The cv-qualifiers apply to the pointer and not to the object pointed to. Similarly, the optional attribute-specifier-seq (10.6.1) appertains to the pointer and not to the object pointed to. 2 Example: The declarations const int ci = 10, *pc = &ci, *const cpc = pc, **ppc; int i, *p, *const cp = &i; 11.3.4 Arrays [dcl.array] 1 In a declaration T D where D has the form D1 [ constant-expressionopt ] attribute-specifier-seqopt and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is an array type; Example: float fa[17], *afp[17]; declares an array of float numbers and an array of pointers to float numbers. si abia mult mai tarziu: Quote 23.11 Smart pointers 23.11.1 Class template unique_ptr [..] 23.11.3 Class template shared_ptr Deci undefined behavior nu e automat "gresit", iar pointeri, array-uri&co. sunt parte integrala a C++, dat fiind ca C++ e o extensie a C, si nu vreun limbaj nou si separat! Cand nu stii ceva, verifici standardul, nu te iei in mod arbitrar dupa un anume ide/compilator - caci nu e garantat ca va detine adevarul absolut si universal! TS030, on 17 aprilie 2019 - 13:26, said:
Nu, exemplul nu este deloc corect! Mai invata inainte de-a-i contrazice pe altii cu atata agresivitate! - nu exista nici un motiv pentru a aloca a (un amarat de int) dinamic - a nu este dealocat - int *a este owning pointer, si se foloseste naked new - cand ai ownership folosesti un smart pointer (unique_ptr by default) Astea chiar sunt reguli simple, usor de inteles si aplicat! Exemplul este pefect corect, in perfect conformitate cu standardul! Sigur nu sunt eu cel care trebuie sa "mai invete"!(in acest caz particular cel putin) TS030, on 17 aprilie 2019 - 13:26, said:
Warning-urile sunt extrem de importante, pana cand dovedesti ca nu sunt. Doar pe la liceu iti permiti sa le ignori. Si iata cum se duce naibii topicul. Warning-uri gcc(g++) pt. int* a = new(int); comanda: Quote g++ -std=c++17 -O0 -g3 -Wall -Wextra -c -fmessage-length=0 -o "src\\Testcpp.o" "..\\src\\Testcpp.cpp" warning-ul: Quote
..\src\Testcpp.cpp: In function 'int main()': ..\src\Testcpp.cpp:16:7: warning: unused variable 'a' [-Wunused-variable] int* a = new(int); ^ g++ -o Testcpp.exe "src\\Testcpp.o" 16:20:36 Build Finished. 0 errors, 1 warnings. asta fiindca nu ai utilizat tu a nicaieri in codul prezentat de tine. Asta e tot. |
#175
Posted 17 April 2019 - 17:51
ca e C sau C++, tu ca programaot trebuie sa ai grija de chestiile astea,
nu inteleg de ce e treaba compilaturului sa te tina de mana |
#176
Posted 17 April 2019 - 17:53
TS030, on 17 aprilie 2019 - 15:43, said:
Mai este inca un aspect: a + b are mai mult sens decat a.append(b) pentru ca rezultatul... nu este a la care ai concatenat b! Este un obiect independent. a.append(b) este semantic echivalent cu a+=b, nu cu a+b. Ca parabellum a mentionat Java: acolo folosesti + sa concatenezi doua stringuri, dar... equals ca sa le compari! Asta e inconsistent. Javascript... nici nu mai vorbesc ce bazaconii se intampla acolo. In java ai StringBuilder/StringBuffer pentru operatiuni mutabile cu stringuri, unde ai append, care face fix un append la un string existent sau gol, nu returneaza un obiect nou. Pe cealalta parte, exista clasa imutabila String care are + overloaded la nivel de compilator(cam singura varianta neabuzabila) si exista si metoda echivalenta concat() - acestea returneaza noi obiecte concatenate |
#177
Posted 17 April 2019 - 18:06
Aha, deci tu tot cu "Java e mai bun!" defilezi pe-aici
C++ are "si una, si alta" prin operatorii + si +=. Mai mult, nu trebuie sa existe exceptii "la nivel de compilator" ca sa mearga. Despre chestia cealalta: Ti-am explicat ca in situatii de undefined behavior compilatorul nu e obligat sa emita warning-uri. Am citat din standard (da, tot ala). Ti-am explicat ca nu e corect codul ala din motiv de undefined behavior. Chiar partea din standard pe care o citezi spune acelasi lucru, ca undefined behavior nu e OK. Mai mult, int[] a = new int[2]; a[4] = 5;arunca exceptie in Java... nema memory safety verificat la compilare. Deci, despre ce vorbim? Edited by TS030, 17 April 2019 - 18:11. |
|
#178
Posted 17 April 2019 - 18:12
#179
Posted 17 April 2019 - 18:14
TS030, on 17 aprilie 2019 - 18:06, said:
Ti-am explicat ca nu e corect codul ala din motiv de undefined behavior. Chiar partea din standard pe care o citezi spune acelasi lucru, ca undefined behavior nu e OK. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), TS030, on 17 aprilie 2019 - 18:06, said:
arunca exceptie in Java... deci, despre ce vorbim? |
#180
Posted 17 April 2019 - 18:21
adamsd, on 17 aprilie 2019 - 18:14, said:
Mi-ai explicat gresit. Tocmai ce ti-am aratat ca "undefined behavior" nu e implicit gresit! Zice standardul: Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message) Daca tie un comportament neprevizibil ti se pare corect, n-avem ce discuta. Apropo, ca tot insisti cu porcaria aia de Java - echivalentul C++ este vector.at(), care de asemenea arunca exceptie la runtime in loc sa permita overflow. Verificarea indexului este optionala in C++ din motive de performanta; intr-un cod bine scris, foarte rar ai nevoie de asa ceva - deci, de ce sa introduci o penalizare la fiecare acces al unui element? Sa ne reamintim cum se itereaza prin toate elementele unui vector in C++: for (auto& elem : vec) Edited by TS030, 17 April 2019 - 18:27. |
Anunturi
▶ 0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users