- Google Pixel topik
- Samsung Galaxy A55 - új év, régi stratégia
- iPhone topik
- Apple iPhone 16 Pro - rutinvizsga
- Realme GT Master Edition - mestermunka
- Karaktere biztos lesz az első Nothing fejhallgatónak
- Apple Watch
- Hivatalos a OnePlus 13 startdátuma
- Íme az új Android Auto!
- Samsung Galaxy S24 Ultra - ha működik, ne változtass!
Új hozzászólás Aktív témák
-
LordX
veterán
válasz
AsterixComic #3101 üzenetére
1. Felelős munkatársak megvetése esetén, általuk való verés elszenvedésével ideiglenesen (code review-ig) helyettesithető.
2. Logikaira ki tudsz találni példát, bitenkénti és-re lásd 1-es pont. -
LordX
veterán
válasz
Boryszka #3091 üzenetére
Ha letörlöd a minta első elemét az 1-20 listából, az nem oldja meg a problémát? 1 elem törlése, 2 sor:
std::vector<int> minta = ...;
std::vector<int> egytolhuszig = ...;
auto torlendo = std::find(begin(egytolhuszig), end(egytolhuszig), minta.front())
if (torlendo != end(egytolhuszig)) { egytolhuszig.erase(torlendo); } -
LordX
veterán
válasz
EQMontoya #3035 üzenetére
Lehet jó falura, de ugyanannyit kell írni (na jó, a függvény/osztálynevek hosszabbak), ha rendesen használsz <random>-ot.
Map: Nem értek egyet: mivel a map node-okban tárolja az adatot, amiben benne van a kulcs, az érték, és jellemzően 3 pointer (left, right, parent), ezért masszívan több memóriát foglal, mint a vector: Az összes általam ismert 64 bites implementációban 32 byte + sizeof(pair<K,V>) a node méret + allocation overhead. Win x64-en a sizeof 16 bye, tehát 40 byte a blokk, ahol az overhead átlagosan 56 byte (!!), azaz 96 byte. Per node. Ja, és a map-nek kell egy extra node (az end node). Szóval 10 elemhez kell 1056 byte heap memória map-el.
Vector esetében ez N*sizeof(int) + overhead, ami most 10*4+56 = 96, összesen a 10 elemre. 100 elemre ez 9696 vs 449 byte.
Szóval ha a cellák több, mint ~9%-át használod ki, akkor a vector nyer map ellen. És még nem is beszéltünk mennyire cache-friendly a vector, és mennyire cache-ellenséges a map; hogy a vektorban indexelsz, nem keresel.
Azért ha tényleg el kell tárolnod a kulcsot, egy kategóriával szebben áll a map, de még mindig vesztésre áll, nem véletlen van a flat_map a boost-ban (ami gyakorlatilag egy map interfész vector felett).
-
LordX
veterán
válasz
jattila48 #2992 üzenetére
Jó, persze ez sarkított példa, én is alapból ++x-et gépelek mindenhol, csak rossz reflexet fejleszt ki a kezdő programozóban, hogy figyelni kell mindenre, különben leharapja a C++ a lábad: "Használj pre-incrementet. Ne adj át érték szerint paramétert függvénynek, adj át const referenciát. Ha lemásolod a paramétert inkább add át érték szerint. Csinálj így, csinálj úgy."
Ha már dolgozol egy éve, akkor amúgy is rájössz, hogy mi az, ahogy elsőre érdemes csinálni.
-
LordX
veterán
válasz
jattila48 #2987 üzenetére
Csak azt mondom, hogy amikor írod a kódot, akkor nem kell görcsölni rajta. Csináld ahogy sikerül, ha hibáztál is, ez soha nem olyan nagy hiba, hogy probléma legyen. Ahol probléma, ott úgyis kiderül az első profilozás után, ahol nem profilozol, ott meg nem probléma.
A program logikájára figyelj, ne arra, hogy itt van egy a kismillió "kötelező" szabály között, ha C++-ban programozol. Ezért van rossz híre a nyelvnek - valójában non-issue az összes ilyen; ha nem akarsz vele foglalkozni, nem kell, semmi nem kötelező.
A programot írjad C++-ban, ne C++ kódot, ami mellékesen megvalósítja a programod.
-
LordX
veterán
válasz
jattila48 #2986 üzenetére
Egyébként én szívem szerint leszedném a publikus verziót, többet árt az egész iparnak, mint használ. Olyan döntések vannak benne (legkirívóbb a kivételek teljes tiltása), amiről már a cégen belül is tudja mindenki, hogy rossz, de a masszív mennyiségű kód miatt nem lehet változtatni.
-
LordX
veterán
válasz
jattila48 #2975 üzenetére
Az operator++() és az operator++(int) csak egy fancy név egy-egy függvénynek. Így most azt mondod, hogy a fordító egy függvényhívást lecserélhet egy másik függvény hívására, ha bizonyos feltételek teljesülnek. Ilyen nincs. Ha másik fordítási egységben van definiálva, akkor teljesen más dolgot csinálhat a kettő, és erről a fordító SEMMIT nem tud.
Ha postfixet írtál a kódba, hót zicher, hogy postfix lesz belefordítva.
-
LordX
veterán
válasz
jattila48 #2967 üzenetére
Ha az iterátorod inkrementálása nem inline, akkor ott valami nagy gáz van..
Ahhoz, hogy úgy működjön a fordító, hogy detektálja, hogy most ki lehet cserélni a pre-t post-ra, úgy, hogy minden esetben működjön, ahogy te leírod, nagyon okosnak kell lennie. Van egy rossz hírem: nem az. Követi a kis szabályait, és az alapján generál/módosít kódot.
Kipróbálni egyszerű, mi van, ha nincs inline __attribute__((noinline)) a függvény definíciója elé GCC/Clang esetében - MSVC-ben meg valami force_no_inline?
Itt nincs RVO, se copy elision - nincs objektum, aminek temporálisból való konstruálása van eltüntetve, hanem bármi objektum konstruálása teljesen - ez már túllép azon, amit ez a szabály enged, és csak azért megoldható, mert se a konstruktor, se a destruktor nem tartalmaz mellékhatást. Ha kikapcsolod az optimalizálást, de force-olod az inline-t a példámban (kapcsolókkal kell játszani, most nincs rá időm kitalálni mit kell), akkor szépen látszana, hogy van pár extra MOV a konstruktor miatt a post-nál (a destruktor meg no-op).
-
LordX
veterán
válasz
jattila48 #2965 üzenetére
Nem érted. A fordító azt fordítja bele, amit írtál. Nem tehet mást. Generál valamilyen köztes kódot (mindegyiknek van, csak egyedül a Clang esetében publikus, az LLVM-IL).
Pre esetben a generált kódra rámozdul az optimalizáló, ami először inline-olja a copy construktort, tehát lesz 1 függvényed, ami másol biteket, azt machinál valamit másik biteken. a következő lépés látja, hogy lemásolsz valami biteket, azt nem használod - fölösleges kód, törölhető.
Post esetben meg nincs copy, nincs mit töröljön.
Az egyik esetben a gép szenvedett egy kicsit érte, de az eredmény ugyanaz, ezért ha nem kritikus kód (ami csak az után derül ki, hogy leprofiloztad!), akkor ne foglalkozz vele, mert nem ér annyit.
Elírtam, fordítva: a WTF a pre-inkrement post-inkrementtel megvalósítva.
-
LordX
veterán
válasz
jattila48 #2963 üzenetére
Az nem épp valid működés, hogy másik operátort fordít, nem változtathatja meg a fordítás a program működését (egyedül copy elision / RVO szabad). Post-increment van itt is, csak elég okos a fordító, hogy kioptimalizálja az extra MOV utasításokat, amik a copy construktorral jöttek létre - módosítsd a példát, hogy legyen valami mellékhatása a copy konstruktornak, máris nem optimizálja ki.
-
LordX
veterán
válasz
MasterMark #2955 üzenetére
if (egy[0].eleje > ketto[0].vege && !nemok) {
auto it = std::find_if( std::rbegin(ketto) //REVERSE begin (gondolom a db2 a 'ketto' konténer mérete)
, std::rend(ketto) //reverse end
, [&](auto&& elem) { return elem.vege < egy[0].eleje; } //keresett feltétel
);
if (it != std::rend(ketto)
kiiras(it->eleje, it->vege);
kiiras(egy[0].eleje, egy[0].vege);
} else { ... } -
LordX
veterán
válasz
jattila48 #2928 üzenetére
Annyira nem eszik forrón a kását. Ha nem használod a visszatérési értéket (mint pl. a for ciklusban), akkor erősen valószínű, hogy optimalizálás után pontosan ugyanazt a kódot generálja akkor is, ha saját operátorokat definiálsz:
[link]
(Az std::slist iterátora kb. így működik, mint a példám, csak ott van még a struktúrában a tárolt elem is.)Szóval nem érdemes ebbe energiát befektetni. Ahol a program logikájához pre-inkrement kell, ott azt kell használni, ahol post, ott azt, ahol mindegy, ott meg mindegy. (De mint korábban írtam, azért ha lehet ne szopassuk az optimizálást fölöslegesen, és használjunk inkább pre-t, egy idő után úgy is az lesz a természetes.)
(BTW, a POD-nak semmi köze ehhez, a példámban a két osztály is POD, és nyilvánvalóan nem triviális ez a két OP.)
-
LordX
veterán
válasz
jattila48 #2924 üzenetére
Vagy csak simán
auto elem = find(begin(tomb), end(tomb), feltetel);
if (elem != end(tomb)) { /* *elem-et kerested */ }- Rövidebb (1 függvény 3 paraméterrel)
- öndokumentáló (vajon mit csinál ez a ciklus ezzel a bonyolult feltétellel vs vajon mit csinál a find függvény)
- ha lassabb kódot generál, akkor sürgősen cseréld le a fordítód, mert konkrétan ugyanaz a kód, miután inline-oltad
- gyorsabb is lehet, ha ki tudja használni a konténer / elem típusát
- nem random access konténerrel (set, list..) is működik -
LordX
veterán
válasz
EQMontoya #2897 üzenetére
Ez talán a link order hülyeség lesz. Nem ignorálja a paraméteredet, hanem hülyén működik a linker: a paraméterek sorrendjében megy végig a linkelendő objektumokon (.cpp esetében forditás után), és belinkeli a {main függvényt, namespace static objektumokat, eddigiek által referált függvényeket}. Szóval a .cpp-ben hiába referálsz a protobuf függvényére, linker nem találja meg, mert nem találkozik vele a cpp után.
Én is falra tudok mászni ettől..
-
LordX
veterán
-
LordX
veterán
válasz
ToMmY_hun #2887 üzenetére
Mégis csak linker hiba lesz (milyen linker mondja meg sorra pontosan, hogy mi hiányzik?) - úgy tűnik nincs bent a lib-ben a függvény. Nézd meg így a lib-et, hogy benne van (most nincs megfelelő tool a gépemen), és ha nincs, akkor annak a buildelésénél kell körülnézned.
-
LordX
veterán
válasz
ToMmY_hun #2884 üzenetére
Ha a fordító adja a hibaüzenetet, akkor mindegy hogy mi a lib, hol van, mivel fordítottad, mert el se jut odáig, hogy az probléma legyen. Vagy nem jó az include, vagy a deklaráció a headerben, vagy a használat. Namespace-eket, paraméter típusokat ellenőrizd, hogy nincs-e valami elgépelve, esetleg ellenőrizd, hogy tényleg jó headert próbálsz behúzni. (Utóbbihoz tipp: a deklaráció mellé tegyél egy #error BLAH direktívát, ha megkapod hibaként, akkor jó. Ha nem, akkor valami más van include-olva.)
-
LordX
veterán
válasz
ToMmY_hun #2882 üzenetére
A fordítási hibának semmi köze nincs a libekhez; azok max a linkernél tudnak hibát okozni.
Normális angolul van a hibaüzenet, nem kell tőle félni
: nincs definiálva a RoboticArm::ArmRunner::getInstance() függvény. Gondolom ez a librarynek egy függvénye, tehát kellene legyen hozzá egy header (RoboticArm.h?), ami tartalmazza a library publikus felületét ( függvények, osztályok, típusok), és be kell #include-olnod.
-
LordX
veterán
válasz
jattila48 #2875 üzenetére
Mivel a Copy elision-t már 12 éve engedi a szabvány, ma már nem nagyon van olyan fordító, ami nem tudná. A 2000-es évek elején még volt.
A szabvány logikáját kell követni: ha valamit copy/direct initialization-el definiálsz, akkor konstruktor overload van. Ez akkor is működik, ha valami kitekert konstruktorod van (const rvalue ref-et váró, leszármazott referenciát váró, stb.). Ha ez megvan, utána jön a "triviális" optimizáció, de ez csak akkor van, ha copy vagy move konstruktor játszik, a fura konstruktorok nincsenek kioptimalizálva - és erősen valószínű, hogy azokat azért csináltad, mert szükséged van rá.
Csak ugye a triviális annyira nem is triviális - mi van, ha van egy olyan kódod, hogy:
T f() { return T(); }
T g() { return f(); }
void h() { T x = g(); }(Tetszőlegesen bonyolult f és g függvényekkel, nem csak ilyen kis Móricka példával.) Hány darab copy/move van itt, amit mellőzni lehet? 1? 2? 4? Erősen attól függ, hogy mit inline-olsz, ami már alapból egy optimizációs kérdés, és másik fordító máshogy dönthet..
-
LordX
veterán
válasz
EQMontoya #2870 üzenetére
Nem, mellékhatással rendelkező konstruktor is áldozatul eshet a copy elisionnek:
[class.copy] bekezdés (jó hosszú alfejezet, a vége felé):
"When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects."
(A "certain criteria" az (N)RVO, a "hagyományos" copy elision és a throw ill catch esetében az exception objektumok konstrukciója listát tartalmazza.)
-
LordX
veterán
válasz
jattila48 #2871 üzenetére
De van, a szabvány ezt mondja, [dcl.init] szekció:
"The initialization that occurs in the form
T x = a;
as well as in argument passing, function return, throwing an exception, handling an exception, and aggregate member initialization is called copy-initialization. [ Note: Copy-initialization may invoke a move. — end note ]
(...)
If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated, and the best one is chosen through overload resolution (13.3). The constructor so selected is called to initialize the object, with the initializer expression or expression-list as its argument(s)."Magyarul, ha a változó és az inicializáló típusa ugyanaz (modulo CV), akkor:
1. Kiértékeli az egyenlő jel jobb oldalát.
2. Overload resolution kitalálja melyik konstruktor kell (azonos típus miatt copy vagy move), és azt hívja meg a jobb oldallal, mint paraméterrel.
Tehát, T x = T();
1. T() default-konstruál egy temporális T-t
2. Overload resolution megtalálja a move konstruktort (vagy ha nincs, copy), és meghivja
3. Expression temporálisa destruálásMivel a bekezdés a direkt inicializálás és a copy inicializálás (ahol az inicializáló kifejezés ugyanolyan típusú) között nem tesz különbséget a T x = valami; és T x{valami}; között, a valami helyére behelyettesítve a T()-t, azt kapod, hogy T x{T()};.
Demo Az -fno-elide-constructors kapcsoló kapcsolja ki a copy elisiont.
-
LordX
veterán
válasz
EQMontoya #2838 üzenetére
struct X {};
struct Y {
Y() = default;
Y(X) {}
Y operator +(const Y& right) { return *this; }
};
Y operator *(const Y& left, const Y& right) { return left; }
void f() {
X x1, x2;
Y y1, y2;
auto t1 = x1 + y1; //member op - nem fordul le
auto t2 = y2 + x2; //member op - lefordul
auto t3 = x1 * y1; //free op - lefordul
auto t4 = y2 * x2; //free op - lefordul
} -
LordX
veterán
válasz
EQMontoya #2835 üzenetére
Erősen ellenjavallott kétoperandusú operátoroknál a tagfüggvényes megvalósítás, ha létezik implicit konverzió más típusokról. Eléggé hülyén néznek a userek, ha a*b lefordul, b*a nem. (Jó, most a mátrixszorzásnál ez nem annyira számít, mert amúgy is csak a megfelelő mérteket kell hagyni.) Ha lehetséges, legyen az operátor szabad függvény, és legyen friend, ha belső dolgokban is turkál.
-
LordX
veterán
válasz
#99472384 #2820 üzenetére
Az Expressben nincs MFC, próbálkozz inkább a Professional-al (Community Edition név alatt ingyenes, nem-kereskedelmi célra).
Az, hogy fél perc, honnan a tökömből vetted? Nincs hozzá projektfájl, úgyhogy minden beállitást meg kell csinálni, ami már alapból nem fél perc.
-
LordX
veterán
válasz
yossarian14 #2796 üzenetére
Milyen platform? Visual Studionak az iostream implementációja sajnos nagyon gyenge teljesítményű, GCC-é (akár MinGW-ben is) jobb (mondjuk annak meg vannak nem-konform hülyeségei, de halandó programozónak nem számít).
Valamint még erősen ajánlott kikapcsolni az io szinkronizálást:
std::ios_base::sync_with_stdio(false); -
LordX
veterán
Nem azt a függvényt deklaráltad friend-é, amit végül definiáltál (más a paraméter), ezért kapod ezt a hibát a fordítótól.
Egyébként a kód kicsit túlbonyolított, még lesz ezen felül is dolgod vele:
- a konstruktor nx5 méretű adatot vár, nem fog működni más mérettel
- Temporálisat referenciaként visszaadni HATALMAS hiba (operator+; add vissza érték szerint)
- a dinamikus tömbök dinamikus tömbje se nem gyors, se nem hibatűrő, erősen ajánlott helyette egy tömböt használni, és az indexelésnél számolni pozíciót.BTW, hol tolják ezt a magyarkodást, fáj olvasni a kommenteket
-
LordX
veterán
válasz
ToMmY_hun #2787 üzenetére
Ha előre tudod a szükséges típust, és csak egyféle kell egy adott helyen, akkor minek tárolod őket egy közös mapban?
Külön map az Effector-nak, Joint-nak, stb, a "factory" (off: én nem hívnám factorynak, mert a factory nem tulajdonosa a legyártás után az objektumnak, ez inkább valami storage) meg a típus alapján template:
Storage<Effector> effectors;
Storage<Joint> joints;
effectors.create("effector1", 1);
joints.create("joint1", 2.0, true);
auto &x = effectors.get("effector1");
auto &y = joints.get("joint1");Teljes kód itt: [link]
Ja, én nem szeretem a naked mutatókat; smart pointer, observing pointer objektum (asszem jön egy standard C++17-el) vagy referencia, különben nem egyértelmű, ki destruálja az objektumot, ha már nem kell.
-
LordX
veterán
válasz
ToMmY_hun #2768 üzenetére
Használd inkább a map::emplace függvényt, az pont arra van kitalálva, hogy új elemet hozz létre a konténerben:
PartCoordinates.emplace(std::piecewise_construct, std::forward_as_tuple("B"), std::forward_as_tuple(10.3f, 45, 456.0f, 54));
A te módszereddel készül egy temporális Matrix objektum, amiből (és a temporális std::string-ből) készítesz egy szintén temporális std::pair, amiből végül az insert move-construct-olja a konténerben a végleges eredményt. Ugyanez igaz az std::string-re is, 2 extra temporális jön létre a kódban. (Mondjuk ilyen kicsi stringek esetében mindegy, de ha nagyobb, mint az SSO méret, akkor meglepően gyenge lesz ennek a kódnak a sebessége.)
Amit én írtam, ott nincs semmilyen temporális objektum, minden forwardolva van. A szintaxis kicsit béna, mert valahogy meg kell különböztetni, hogy az egyébként 5 paraméter közül melyik a kulcs melyik az érték paramétere, de a többi konténerben csak simán felsorolod a konstruktor paramétereket:
std::vector<Matrix> foo;
foo.emplace_back(1,2,3,4);
Új hozzászólás Aktív témák
Hirdetés
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Azonnali fáradt gőzös kérdések órája
- Kertészet, mezőgazdaság topik
- Folyószámla, bankszámla, bankváltás, külföldi kártyahasználat
- AMD vs. INTEL vs. NVIDIA
- Hálózati / IP kamera
- Autós topik
- Lenovo Legion 5i 15 notebook: légiós fegyverzetben
- Google Pixel topik
- Elektromos rásegítésű kerékpárok
- Formula-1
- További aktív témák...
- Szép Dell Latitude 7320 -60% "Kis Gamer" Üzleti Profi Ultrabook 13,3" i7-1185G7 32/512 FHD IRIS Xe
- LG NanoCell 50NANO759PR
- Samsung Galaxy S23 256GB (garis)
- i7 8700/ 32GB DDR4/ 512GB gen4 SSD/ R5 430 2GBD5/ HP 400G5 SFF/ garancia/ ingyen foxpost
- HUAWEI WATCH GT5 46 mm Active, két hetes készülék, kb 23 hó garancia, ÜZLETBŐL
- LG 77G4 - 77" OLED evo - 4K 144Hz 0.1ms - MLA - 3000 Nits - NVIDIA G-Sync - AMD FreeSync - HDMI 2.1
- Csere-Beszámítás! MSI Gaming X RTX 4060Ti 16GB GDRR6 Videokártya!
- ÁRGARANCIA!Épített KomPhone Ryzen 7 9800X3D 32/64GB RAM RX 9070 XT 16GB GAMER PC termékbeszámítással
- Bomba ár! Lenovo ThinkPad X395 - AMD Ryzen PRO 5 I 8GB I 512GB SSD I 13,3" FHD I Cam I W11 I Gari!
- AKCIÓ! AMD Ryzen 9 3900X 12 mag 24 szál processzor garanciával hibátlan működéssel
Állásajánlatok
Cég: PC Trade Systems Kft.
Város: Szeged
Cég: Promenade Publishing House Kft.
Város: Budapest