IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Dá se někde najít definice defaultních konstruktorů a destruktorů?

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
xmms
Člen
Avatar
xmms:23.9.2019 15:47

Kde se dá zjistit konkrétní definice konstruktorů a destruktorů, které překladač automaticky vygeneroval?

Zkusil jsem:

class Trida
{
private:
        int baf;
public:
//kde je Trida(){} a ~Trida(){} ?
        void setbaf() { baf + 1; }

};

Chci docílit: Chci vědět, co můj program přesně dělá. V knize píšou, že to vytváří a ruší objekty, ale konkrétní zdroják jsem na to nenašel. Chci vidět všechno, co můj program obsahuje. Třeba by se tam dalo najít vysvětlení, proč programy typu hello world můžou mít i několik megabajtů...

 
Odpovědět
23.9.2019 15:47
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na xmms
Martin Dráb:23.9.2019 16:35

Kde se dá zjistit konkrétní definice konstruktorů a destruktorů, které překladač automaticky vygeneroval?

Nevím, zda-li se dají defaultní konstruktory a destruktory najít ve formě zdrojového kódu. Jelikož C++ snad stále nemá reflexi, myslím si, že budou vždy generované překladačem, protože:

  • defaultní konstruktor zavolá defaultní konstruktor na všechny atributy třídy,
  • defaultní destruktor zavolá defaultní destruktory všech atributů třídy.

Myslím, že je tam ale jedna výjimka, a to případ, kdy třídě vytvoříš vlastní konstruktor. Pak pro ni není generován ten defaultní.

Chci vidět všechno, co můj program obsahuje. Třeba by se tam dalo najít vysvětlení, proč programy typu hello world můžou mít i několik megabajtů...

Podívej se na tvůj program třeba v disassembleru typu IDA Pro (nějaká verze by měla být i zdarma a měla by na toto stačit). Máš-li zapnuté ladící symboly, i v disassembleru uvidíš jména funkcí, globálních proměnných... a dozvíš se, co všechno bylo do binárky zahrnuto (což se třeba odvíjí od toho, zda-li povolíš překladači/linkeru vyházet věci, které se v programu prokazatelně nepoužívají).


Pokud Hello World naprogramuješ jako

std::cout << "Hello World" << std::endl;

nemůžeš se divit, že velikost výsledné binárky může být značná. Zvláště pokud kompiluješ pomocí mingw na Windows, tedy nepoužíváš běhové knihovny od Microsoftu (jelikož v MS znají ten jejich OS, dokážou napsat menší běhové knihovny). std::cout je stream, což je dosti bohatá třída skládající se ze spousty věcí, které pak musí být také zahrnuty do binárky. Dále k tomu můžeš připočítat kód řešící obsluhu výjimek... a postupně se to nabalí.

Nahoru Odpovědět
23.9.2019 16:35
2 + 2 = 5 for extremely large values of 2
Avatar
xmms
Člen
Avatar
Odpovídá na Martin Dráb
xmms:23.9.2019 22:53

Používám Microsoft visual studio a někdy g++ v mingw. Dá se nějak jednoduše nastavit kompilátor, aby tam dával jen funkce, které program potřebuje? Třeba ve visual studiu musím zahrnout runtime library v sekci code generation bez toho DLL, aby program nebyl závislý na nainstalovaných Visual C++ Redistributable, jinak by to házelo chybu, že mu chybí knihovna. Program má kvůli tomu cca o 250 kB navíc.

 
Nahoru Odpovědět
23.9.2019 22:53
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na xmms
Martin Dráb:23.9.2019 23:58

Třeba ve visual studiu musím zahrnout runtime library v sekci code generation bez toho DLL, aby program nebyl závislý na nainstalovaných Visual C++ Redistributable, jinak by to házelo chybu, že mu chybí knihovna. Program má kvůli tomu cca o 250 kB navíc.

Ano, je to tak. Použitím C++ ti program opravdu hezky "nakyne", protože STL je prostě taková mamutí a zřejmě překladači dělá problém vyházet funkce, které se nepoužijí. Vezmi si třeba kus kódu:

if (x)
  a();
else b();

Ty můžeš vědět, že x bude vždy nenulové (a tedy se bude vždy volat a, b se nikdy volat nebude, takže jej nemusíš do binárky vůbec zahrnout), ale pro překladač toto může být velmi velmi netriviální (obvykle nemožné) zjistit. Navíc, pokud se takový kód nachází v šablonované funkci, která je několikrát instanciována, pro každou instanci se takhle zvláště nevyignoruje příslušná instance funkce b.

Pokud chceš menší binárku (a nechce používat nějaký externí packer aka UPX):

  • piš v Céčku, neb to nenabere s sebou tolik balastu,
  • nepoužívej běhovou knihovnu vůbec (/NODEFAULTLIB), ale uznávám, že je dost peklo si naimplementovat potřebné funkce vlastními silami.

Dost funkcí (memset, memmove, memcmp, fopen, fclose, fread, fwrite...) lze poměrně jednoduše implementovat prostřednictvím Windows API (které jsou samy implementovány na každém Windows, takže je nemusíš tahat s sebou). Myslím, že seženeš i snprintf (user32.dll?, ntdll.dll?). Případně si můžeš implementovat jen podmnožinu, kterou potřebuješ.

I třeba taková zdánlivě jednoduchá funkce pro kopírování paměti - memcpy může zabírat pár set bajtů jen protože, obsahuje různé varianty pro kopírování různě velkých bloků dat (za využití SSE a jiných speciálních instrukcí).

Ale bez běhové knihovny se žije dost těžko, to přiznávám. Musíš si sám naparsovat příkazovou řádku, sám se případně postarat o konzoli... a nebo se striktně vyvarovat použití funkcí z téhot knihovny. Překladač je pak vyhází, ale i tak ponechá ty, které jsou součástí inicializace a finalizace.

Nahoru Odpovědět
23.9.2019 23:58
2 + 2 = 5 for extremely large values of 2
Avatar
Patrik Valkovič:24.9.2019 0:04

Řešit kB v době, kdy obrázky mají jednotky MB a filmy mající několik GB streamujeme realtime přes internet, se mi zdá poněkud přehnané. Pokud se nejedná o miktrokontrolery s omezenou pamětí (které by byly spíše programované v C), nevidím důvod takové věci vůbec řešit.
#justsaying

Nahoru Odpovědět
24.9.2019 0:04
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Caster
Člen
Avatar
Caster:4.10.2019 17:53

Pokud jde o rychlost a úsporný kód, udělám si příslušné funkce v x64 assembleru. V C++ jsem si např. alokoval 4 GB RAM, načetl do ní na 2x po 2,5 GB textový soubor a pak v assembleru pracoval s 38 miliony řádků ;-).

 
Nahoru Odpovědět
4.10.2019 17:53
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na Caster
Martin Dráb:4.10.2019 20:33

a pak v assembleru pracoval s 38 miliony řádků ;-).

To není problém ani bez použití Assembleru. Jenom je potřeba vyhnout se C++kovým streamům, protože výkon jaksi asi nebyl jedním z cílů při jejich návrhu...

Nahoru Odpovědět
4.10.2019 20:33
2 + 2 = 5 for extremely large values of 2
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:4.10.2019 20:55

Moc dobře si pomatuji o jakou aplikaci se jedná. Společně jsme tu řešili drobné neance a nepochybuji o funkčnosti aplikace. Přesto bych se zaměřil na optimalizaci datových souborů, ze kterých souřadnice o průběhu letu taháš. A to by bylo aby se rychlost vykreslení trasy drasticky nesnížila, stejně tak jako paměťové nároky... :-)

Nahoru Odpovědět
4.10.2019 20:55
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:5.10.2019 1:48

Začátky byly těžké, ale s pomocí zdejších expertů jsem to dal dohromady, díky, pomoc a rady velmi oceňuji :-).

 
Nahoru Odpovědět
5.10.2019 1:48
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.