cpp_tips
Toto je starší verze dokumentu!
Obsah
Tipy & triky C++
char* do istringstrem
- jak z velkého pole znaků udělat istringstream bez kopírování v paměti?
- následující kód paměť kopíruje až 3x (záleží na implementaci copy on write)
char *mybuf[] = "very very .. long"; istringstream myss(string(mybuf, strlen(mybuf)));
- finta
char *mybuf[] = "very very .. long"; istringstream dfile; dfile.rdbuf()->pubsetbuf(mybuf, strlen(mybuf));
- ověřil jsem to zavoláním free na mybuff (kód se musí upravit na dynamickou alokaci mybuf)
Default parametry metody/funkce
- mám metodu s více parametry. Někdy mi ale stačí změnit jen ten první a ostatní jako default
- jako default lze dokonce použít i funkci nebo proměnou
// declaration void setSomething(int val1 = 1, int val2 = 2, int val3 = 3); // definition void setSomething(int val1, int val2, int val) { this.val1 = val1; this.val2 = val2; this.val3 = val3; } // calling setSomething(1); setSomething(1,2); setSomething(1,2,3);
Zákeřné dočasné objekty
- dočasné objekty mají životnost pouze v rámci výrazu
- příklad se stringstream: chceme postupně vyčítat všechny znaky stringu
- první varianta
- v každé iteraci se provádí znovu alokace paměti pro dočasný objekt str včetně kopírování obsahu
- nejspíš dokonce dvojnásobně, ještě pro volání size
- valgrind naměřil (celý program): total heap usage: 9,890 allocs, 9,868 frees, 1,207,634 bytes allocated
int i; for (i=0; i<outstr.str().size(); ++i) { hash = ((hash << 5) + hash) + outstr.str()[i]; // hash * 33 + c }
- druhá varianta
- vůbec nefunguje - nekončeně cyklí kvůli memory leaku
for (string::const_iterator it = outstr.str().begin(); it != outstr.str().end(); ++it) { hash = ((hash << 5) + hash) + *it; // hash * 33 + c }
- třetí varianta
- správné řešení
- teoreticky se ale kopíruje paměť str objektu do mystr
- valgrind naměřil (celý program): total heap usage: 9,148 allocs, 9,126 frees, 913,802 bytes allocated
string mystr(outstr.str()); for (string::const_iterator it = mystr.begin(); it != mystr.end(); ++it) { hash = ((hash << 5) + hash) + *it; // hash * 33 + c }
- čtvrtá varianta
- mělo by být nejvíce šetrné k paměti
- objekt str by se neměl kopírovat, měla by se pouze prodloužit jeho životnost
- hrozí zde stále nebezpečí přepsání obsahu.. ukazatel ukazuje na interní buffer, který se může při práci se stringstream měnit
- valgrind naměřil překvapivě stejný počet alokací, jako v předchozím případě. Nejspíš zabrala nějaká optimalizace při kompilaci
const string& mystr = outstr.str(); for (string::const_iterator it = mystr.begin(); it != mystr.end(); ++it) { hash = ((hash << 5) + hash) + *it; // hash * 33 + c }
Převod struct na/z string (serializace)
- struktura je v C++ ve skutečnosti třída, která má všechny položky public (žádný rozdíl mezi nimi není)
- v C se struktura dala krásně využít pro parsování pole znaků, například hlavičky paketu
- v C++ lze samozřejmě používat stejným způsobem, ale jak by pro tento úkol šlo použít nové vlastnosti C++?
- pokud struktura obsahuje pouze základní datové typy,
- lze strukturu převést na string zápisem do proudu stringstream po přetypování na pole znaků:
stringstream out(stringstream::out|stringstream::binary) out.write((char *) &acc, sizeof(struct MyRecord));
- pokud obsahuje i objekty, jako například string,
- musí se zapsat po jednotlivých typech:
.. out.write( rec.location.c_str(), rec.location.size() ); // string out.write( (char*) & rec.account_num, sizeof( rec.account_num ) ); // int ..
- a nebo prý pomocí speciálního
out.write(reinterpret_cast<char *>(&acc), sizeof(MyRecord));
- čtení probíhá obdobně… voláním funkce read
cpp_tips.1461597347.txt.gz · Poslední úprava: (upraveno mimo DokuWiki)
