Pāris vietās nākas nodarboties ar string interning, lai samazinātu datu apjomu atmiņā. Tas nozīmē glabāt visas unikālās virknes vienā eksemplārā. Kādreiz mans kods, kas to darīja, aizņēma aptuveni 20 rindiņas un glabāja rādītājus uz unikālām simbolu virknēm. Bet tas nebija forši, jo rādītāji kādreiz var rādīt uz nekurieni un viss kods jāpārraksta izmantojot rādītājus.
Nesen vēlreiz paskatījos uz StringPool realizāciju un aizdomājos par std::string govi, kas piemīt GCC lietotajai STL realizācijai. Īsumā – ja tiek kopēts std::string objekts, reālā simbolu virkne netiek kopēta, tikai palielināts referenāu skaits. Tikai tad, kad objekts tiek legāli modificēts ar std::string metodēm, tiek veidota kopija un veiktas izmaiņas tajā. Savukārt gadījumos, kad izmaiņas tiek veiktas nelegāli:
std::string a = "foobar";
std::string b = a;
*((char *)a.c_str() + 3) = '\0';
“pēkšņi” tiek mainīti nesaistīti objekti. Š ajā gadījumā b ir “foo”, nevis “foobar” kā būtu gaidāms. Augstāk redzamais ir slikts kods, bet vairākas reizes ir nācies tādu sastapt.
Tā kā vienmēr tiek lietota GCC STL realizācija, tagad man ir jauna, uz šo brīdi īsākā, versija par std::string interning bez rādītāju izmantošanas:
typedef std::set<std::string> StringPool;
StringPool strings;
std::string foo = *strings.insert(getSomeString()).first;