Uživatelské nástroje

Nástroje pro tento web


cpp_tips

Toto je starší verze dokumentu!


Tipy & triky C++

char* na istringstrem (bez kopírování)

  • 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)
  • metoda pubsetbuf je nabízena třídou streambuf, ale implementována až v strbuf nebo filebuf (takže v streambuf nedělá vlastně nic)

char* do vector<char>

char arr[] = "abcd";
vector<char> buff;
buf->insert(buf->end(), arr, arr + strlen(abcd);

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
..
  • čtení probíhá obdobně… voláním funkce read
cpp_tips.1462969680.txt.gz · Poslední úprava: (upraveno mimo DokuWiki)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki