tak jo... tak hodíme za hlavu tu nostalgiii, a vrhneme se opět na mudrování o tom, kudy a zda vůbec vede cesta do budoucnosti pro ANSI C a zejména jeho aktuálnější verze (C99, případně C0x - tedy pokud bude vyhlášené nejen C++0x ale i C0x) ?
máme zde celou škálu přístupů, od konzervativního "malloc a free musí stačit každému - aspoň vím co dělám, když to dělám" (toto je srovnatelné s přístupem "masturbace je TAKY bezpečný sex - aspoň nikdo neotěhotní" :-) - až po různé více či méně extravagantní přístupy.
já popravdě v poslední době víc přemýšlel o těch metaobjektech, které by měly doplňující informace někde na adresách ptr-1, ptr-2. vlastně nejsou ani tak neslučitelné s tím "vykrajováním" podmnožin z primitivních datových struktur - naopak, pokud je metaobjekt doplněný informací o reálné délce, tak je možné ho použít k předání k sub-pole či sub-stringu i jenom s minimálním množství přídavných informací - a navíc je to argument proti NULL terminated stringům.
představuju si to asi nějak takhle:
ptr - odkazuje přímo na string, začátek C pole, apod., je indexovatelný pomocí C hranatých závorek, apod. - ovšem pozor, může to být taky přímo int, long, float...
ptr - 1: obsahuje pointer na "interface" objektu (a tedy lze z toho vyčíst i typ objektu)
ptr - 2: obsahuje informaci o aktuální velikosti
ptr - 3: obsahuje informaci o alokované velikosti
ptr - 4: reference counter (sic! ale "klonovací funkce", vytvářející nový metaobjekt, bez skutečného kopírování samotného obsahu paměti, by ho mohla vždy aktualizovat... )
výhody:
- jednotlivé instance metaobjektu se deklarují prostě jako pointery na daný primitivní typ
- přiřazení = zůstává přiřazením, vytvořením další reference (myšleno reference na úrovni C zdrojáku, ne nové reference ve smyslu zvýšení počtu metaobjektů odkazujících na stejný flák paměti)
- "interface" může snadno obsahovat sadu základních "metod" - typu serializace, zjištění délky, ověření validity obsahu, apod.
- vytvoření "klonu" metaobjektu nebo "vyříznutí" podmnožiny objektu nemusí být spojené se skutečným kopírováním obsahu paměti
- konvence, která by předpokládala vždy volání funkcí interfacu (např. length() apod.) a ne přímé čtení paměti, by elegantně řešila např. přístup k metaobjektu typu FILE, apod.
- makra, určená na přístup k interfacu objektu, by mohla teoreticky před voláním kontrolovat, zda na adrese ptr -1 je skutečně odkaz, na nějaký definovaný interface (pomalé, ale robustní - použitelné pro případ, že by definovaných interfaců byl jenom nějaký předem známý, nízký počet)
nevýhody:
- totální průser pokud někdo tenhle přístup použije na nekompatibilní pointer (ovšem toto je v C průser vždy, takže jsme jenom tam, kde jsme byli od začátku)
- totální průser, pokud to celé zapomeneme inicializovat
- zbytečné plýtvání pamětí pro metaobjekty typu int, long, apod. a netriviální zápis matematických operací (na drouhou stranu - nepředpokládá se, že by se to na toto používalo)
- pokud chceme zobecnit např. i na spojové seznamy, tak bude nutné předdefinovat nějaká pevná pravidla jak vypadají (např. "na začátku každého záznamu je vždy odkaz na další záznam)
- pochopitelně tím nezískáme automatické uvolnění paměti (ale zase s rozumnou správou paměti může počítat inicializační funkce, "konstruktor" metaobjektu)