Vlákno názorů ke článku JSON pro C++11 s immutabilním DOMem. od Jan Korous - Pokud bych resil pouze garanci nemennost dat. V...

  • 13. 1. 2017 15:37

    Jan Korous (neregistrovaný)

    Pokud bych resil pouze garanci nemennost dat. V cem je lepsi mit specialni "immutable" strukturu proti sdileni instance "bezne" struktury pomoci const reference?

  • 13. 1. 2017 16:35

    Ondřej Novák

    Pokud umožňujete kopírovat sdílením, tedy že máte konstruktor který přijímá const referenci a provede sdílení, pak vám const nepomůže, protože ho tímto způsobem obejdete

    Pseudo příklad

    const Value cv = {10,20,30}
    Value v (cv);
    v.push_back(40); // < změní se i cv!!;

    Musel byste se vzdát jiných věcí. Tak například kopírování sdílením... tedy vytvářet plnohodnotné kopie. Kopírovací konstruktor by při přijmu const hodnoty prostě nemohl sdílet, musel by kopírovat. Přitom pokud kopírujete do objektu o kterém víte, že taky bude pouze const, pak je vytváření hluboké kopie zbytečné. Kopírovací konstruktor však tuhle informaci nemá

    Value x(y); // potřebuju kopii
    const Value x(y); // mohu sdílet.

    Já to ze začátku řešil tak, že jsem měl dvě třídy. Value a ConstValue. Objekty Value by obsahovaly měnitelné kontejnery, objekty ConstValue by se měnit nedaly. No jenže co když chcete mít měnitelný kontejner konstantních kontejneru? Kterou třídu na to použijete? Já zavedl třetí....

    No výsledek nebyl vůbec přehledný. Navíc jsem časem zjistil, že používám v zásadě jen ConstValue a objekty, kterým jsem říkal buildery, tedy něco, co mi pomáhá vytvořit kontejner (objekt , pole) než z něho udělám ConstValue. A tak jsem to celé přepsal do současné podoby.

  • 14. 1. 2017 13:04

    Jan Korous (neregistrovaný)

    Ptal jsem se proto, ze sam jsem nad podobnou otazku hloubal a klonil se spise k opacnemu zaveru, zajimal mne Vas nahled.

    Mozna se tedy zeptam jinak - k cemu je kopirovani sdilenim dobre? Proc proste nepouzit const referenci?
    Proc to neresit stylem:
    Value x(y); // potřebuju kopii
    const Value& x = y; // mohu sdílet. (... lifetime y bych nyni neresil)

    Jde Vam o moznost jak se priblizit pouziti STL kontejneru const objektu nebo neco jineho?

  • 14. 1. 2017 23:20

    Ondřej Novák

    Celé je to o tom vyhnout se dělání hlubokých kopií. JSON dokument může být velký, může být sestaven z mnoha částí.

    Value result = {result1, result2, result3,...,re­sultN}

    pokud result1 až resultN jsou všechno nějaké JSON kontejnery, pak stojíte před otázkou: Výše uvedený příklad
    a) udělá kopie výsledků?
    b) bude je sdílet?

    asi a) je správnější, jenže... pokud každý ten result má několik megabajtů nebo strukturu do 10. úrovně pak přistupujete ke kroku b). Jenže tohle nemůžete udělat, pokud existuje někdo, kdo může obsah result1 až resultN změnit, třeba tak, jak měníte obsah proměnné typu vektor, a protože jsou ty kontejnery sdílené, změna se uplatní všude, kde je se to sdílí. On to bude měnit ve své instanci, která není označená const, přestože vy třeba držíte const verzi. Naprosto stejně funguje JavaScript, jen si to zkuste. Udělám kopii kontejneru, dojde ke sdílení

    aa = [10,20,30];
    bb = aa;
    aa.push(40);
    console.log(bb);

    >[10, 20, 30, 40]

    Takže výsledkem je, že nemohu použít ani a) a ani b)
    Ještě je tu c) - totiž, že ze všeho udělám konstanty. Konstanty mohu sdílet, protože se nemění.

    Jak si jednotlivé varianty vypadají při změnách?
    a) mohu měnit co chci, mám kopii (tu musím udělat vždy)
    b) mohu měnit jen to co není sdílené, nebo přijmout fakt, že se ta změna projeví jinde
    c) pokud chci měnit, musím si udělat kopii toho co měním (mělká kopie)

    ImtJSON je právě implementace DOMu variantou c).

    Tím jsem odpověděl na otázku "k cemu je kopirovani sdilenim dobre?"
    "Proc proste nepouzit const referenci?".Když sdílím, const reference nefungují. Mohu si udělat kopii sdílením. Aby const reference fungovaly, musím se vrátit k a).

    PS: K variantě a), představte si, že sestavujete JSON dokument odspoda nahoru. Na každé úrovni kopírujete vše ze spodní úrovně tak, jak vkládáte prvky do kontejnerů... já vím, že jde použít std::move a přesouvat místo kopírování... dokud vám někdo ty výsledky neposkytnul jako const referenci.... pak kopírovat musíte