{"id":386,"date":"2018-11-09T07:30:38","date_gmt":"2018-11-09T06:30:38","guid":{"rendered":"https:\/\/www.kompikownia.pl\/?p=386"},"modified":"2018-11-22T21:13:06","modified_gmt":"2018-11-22T20:13:06","slug":"uniform-initialization-prostota-wypelniania-struktur-danych","status":"publish","type":"post","link":"https:\/\/www.kompikownia.pl\/index.php\/2018\/11\/09\/uniform-initialization-prostota-wypelniania-struktur-danych\/","title":{"rendered":"Uniform Initialization &#8211; prostota wype\u0142niania struktur danych"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">&lt; 1<\/span> <span class=\"rt-label rt-postfix\">minut\u0119<\/span><\/span><p>Programuj\u0105c w C++, z pewno\u015bci\u0105 wiesz jak inicjuje si\u0119 zmienne. Nie jest to czynno\u015b\u0107 skomplikowana. Troch\u0119 wi\u0119cej problem\u00f3w zachodzi kiedy musisz zainicjowa\u0107 tablic\u0119 lub jaki\u015b kontener. Stosujesz wtedy pewnie p\u0119tl\u0119 for. Je\u015bli musisz doda\u0107 kilka lub kilkana\u015bcie element\u00f3w do kontenera vector, stosujesz metod\u0119 push_back, wywo\u0142uj\u0105c j\u0105 r\u0119cznie albo w p\u0119tli. Nie jest to rozwi\u0105zanie z\u0142e \u2013 gdy\u017c dzia\u0142a. Jednak\u017ce, standard C++11 wprowadzi\u0142 w tym wzgl\u0119dzie du\u017ce udogodnienie. Jest nim tzw. \u201euniform initialization\u201d. Po polsku mo\u017cna by\u0142oby to przet\u0142umaczy\u0107 jako \u201ejednolita inicjalizacja\u201d.<\/p>\n<h2 class=\"western\">Jak wygl\u0105da uniform initialization?<\/h2>\n<p>W starszym C++ znajduje si\u0119 du\u017co r\u00f3\u017cnorodno\u015bci. Inaczej zainicjujemy element klasy, inaczej wype\u0142nimy zwyk\u0142\u0105 tablic\u0119 o sta\u0142ym rozmiarze a inaczej kontener vector. Sp\u00f3jrz na poni\u017cszy przyk\u0142ad, napisany w starym C++.<\/p>\n<pre line=\"1\" lang=\"cpp\">\r\n#include <iostream>\r\n#include <vector>\r\n#include <list>\r\n#include <map>\r\nusing namespace std;\r\n\r\nint main()\r\n{\r\n    int tab[] = {1,2,3,4,5};\r\n    list<int> normal_list;\r\n    for(int i = 0;i<5;i++) normal_list.push_front(i+1);\r\n    map<int,string> normal_map;\r\n    normal_map[0] = \"zero\";\r\n    normal_map[1] = \"one\";\r\n    normal_map[20] = \"two\";\r\n    vector<int> vec;\r\n    vec.push_back(100);\r\n    vec.push_back(200);\r\n    vec.push_back(300);\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Zobacz wielorako\u015b\u0107 form inicjacji poszczeg\u00f3lnych rodzaj\u00f3w zmiennych, tablic czy kontener\u00f3w. Do wype\u0142nienia zwyk\u0142ej tablicy u\u017cywamy nawias\u00f3w klamrowych. Lecz w przypadku listy u\u017cywamy p\u0119tli z metod\u0105 push_front. Map\u0119 wype\u0142niamy tre\u015bci\u0105 w jeszcze inny spos\u00f3b. W ko\u0144cu kontener vector \u2013 kt\u00f3ry u\u017cywa metody push_back.<\/p>\n<p>Czy nie da\u0142oby si\u0119 tego zrobi\u0107 jako\u015b pro\u015bciej? Sp\u00f3jrz, jak to mo\u017cna wykona\u0107 w C++11.<\/p>\n<pre line=\"1\" lang=\"cpp\">\r\n#include <iostream>\r\n#include <vector>\r\n#include <list>\r\n#include <map>\r\nusing namespace std;\r\n\r\nint main()\r\n{\r\n    int tab[] {1,2,3,4,5};\r\n    list<int> normal_list {1,2,3,4,5};\r\n    map<int,string> normal_map {{0,\"zero\"},{1,\"one\"},{2,\"two\"}};\r\n    vector<int> normal_vector {100,200,300};\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Jak widzisz wype\u0142niamy w ten sam spos\u00f3b ka\u017cdy rodzaj kontenera. Nie jest wa\u017cne czy to vector, zwyk\u0142a tablica o okre\u015blonym rozmiarze czy mapa. W ka\u017cdym wypadku stosujemy nawiasy klamrowe, w kt\u00f3rych wypisujemy warto\u015bci kt\u00f3re maj\u0105 zosta\u0107 dodane do kontenera.<\/p>\n<p>M\u00f3g\u0142by\u015b zapyta\u0107, jak fachowo nazywaj\u0105 si\u0119 te nawiasy klamrowe? Zaspokoj\u0119 twoj\u0105 ciekawo\u015b\u0107. Jest to lista inicjalizacyjna. (Nie myl z list\u0105 inicjalizacyjn\u0105 konstruktora).  <\/p>\n<h2 class=\"western\">Kluczowe r\u00f3\u017cnice<\/h2>\n<p>W starszym standardzie C++ przy inicjacji zmiennych danymi warto\u015bciami istnia\u0142y trzy r\u00f3\u017cne przypadki:<\/p>\n<ul>\n<li><strong>()<\/strong> &#8211; zwyk\u0142e nawiasy. Wykorzystywane wtedy, kiedy klasa posiada konstruktor, kt\u00f3ry zajmuje si\u0119 przygotowaniem jej do pracy.<\/li>\n<li>{} &#8211; u\u017cywany przy strukturach.<\/li>\n<li><strong>Brak nawias\u00f3w<\/strong> \u2013 normalna inicjacja zmiennych, za pomoc\u0105 operatora przypisania<\/li>\n<li><strong>Specjalna metoda<\/strong> \u2013 np.: push_back w przypadku vector.<\/li>\n<\/ul>\n<p>Teraz nie musimy si\u0119 niczym przejmowa\u0107. Przy wst\u0119pnym wype\u0142nianiu kontenera\/tablicy warto\u015bciami, mo\u017cemy bezpiecznie u\u017cywa\u0107 nawias\u00f3w klamrowych {}. Ka\u017cdy nowszy kompilator sobie z tym bez problemu poradzi.<\/p>\n<h2 class=\"western\">Uniform initialization i klasy<\/h2>\n<p>Wskoczmy na nieco wy\u017cszy poziom. Zobaczmy, ile da nam uniform initialization przy klasach w\u0142asnej produkcji. Zerknij na poni\u017cszy kod. Najpierw przeanalizuj go samodzielnie. Potem przewiniesz stron\u0119 i przeanalizujemy go wsp\u00f3lnie :).<\/p>\n<pre line=\"1\" lang=\"cpp\">\r\n#include <iostream>\r\n#include <vector>\r\n#include <utility>\r\nusing namespace std;\r\nstruct Foo {\r\n    int x;\r\n    float y;\r\n};\r\nclass Bar {\r\n    public:\r\n    Bar(int _x,float _y) : x(_x),y(_y) {}\r\n    private:\r\n    int x;\r\n    float y;\r\n};\r\npair<double,double> multiplyVectors(pair<double,double> v1,pair<double,double> v2) {\r\n    return pair<double,double>(v1.first*v2.first,v1.second*v2.second);\r\n}\r\nint main()\r\n{\r\n    \/\/tworzenie obiekt\u00f3w za pomoc\u0105 konstruktora domy\u015blnego\r\n    Foo fooObject;\r\n    Foo fooObject2();\r\n\r\n    \/\/tworzenie obiekt\u00f3w za pomoc\u0105 konstruktora w\u0142asnego\r\n    Foo FooObjectAggregate {3,3.5f};\r\n    Bar BarObjectWithConstructor(3,3.5f);\r\n\r\n    \/\/troch\u0119 zabawy z vectorami\r\n    vector<Bar> vectorOfBars;\r\n    vectorOfBars.push_back(Bar(1,1));\r\n    vectorOfBars.push_back(Bar(2,2));\r\n    vectorOfBars.push_back(Bar(3,3));\r\n    pair<double,double> result = multiplyVectors(pair<double,double>(2.0,2.0),pair<double,double>(3.0,4.0));\r\n\r\n    \/\/Tablice\r\n    Foo arrOfFoos[] = {{1,1.0f},{2,2.0f},{3,3.0f}};\r\n    Bar arrOfBars[] = {Bar(1,1.0f),Bar(2,2.0f),Bar(3,3.0f)};\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Tworzymy sobie struktur\u0119 Foo i klas\u0119 Bar. (linijki 5-15). Tworzymy sobie tak\u017ce prost\u0105 funkcj\u0119, kt\u00f3ra z pomoc\u0105 pair pozwala nam na pomno\u017cenie dw\u00f3ch wektor\u00f3w (tych matematycznych :)).<\/p>\n<p>W linijkach 22 i 23 tworzymy obiekt klasy Foo. Pierwszy spos\u00f3b (22) tworzy obiekt wype\u0142niony domy\u015blnymi warto\u015bciami. Drugi natomiast jest o wiele bardziej problematyczny. Spodziewa\u0142by\u015b si\u0119 pewnie, \u017ce zostanie utworzona zmienna o nazwie fooObject2 typu Foo. Tak si\u0119 jednak nie stanie. Linijka ta wygl\u0105da jak wywo\u0142anie konstruktora domy\u015blnego &#8211; to fakt. W rzeczywisto\u015bci jednak jest do deklaracja funkcji, kt\u00f3ra zwraca Foo i nie przyjmuje \u017cadnych argument\u00f3w. Gdyby\u015bmy spr\u00f3bowali odwo\u0142a\u0107 si\u0119 do zmiennej x lub y obiektu fooObject2, nie uda nam si\u0119 to. <\/p>\n<p>W linijce 26 i 27 mo\u017cemy wykona\u0107 kolejne por\u00f3wnanie. Struktur\u0119 mo\u017cemy wype\u0142ni\u0107 za pomoc\u0105 listy inicjalizacyjnej. Jednak\u017ce, dla klasy musimy wywo\u0142a\u0107 konstruktor.<\/p>\n<p>Zobaczmy, jak mo\u017cemy doda\u0107 obiekty naszej klasy do kontenera vector. No c\u00f3\u017c, wygl\u0105da to standardowo, co ukazuj\u0105 linijki 30-33. Za ka\u017cdym razem musimy wywo\u0142ywa\u0107 metod\u0119 push_back. Nast\u0119pnie, jako argument podajemy konstruktor obiektu z okre\u015blonymi argumentami.<\/p>\n<p>Funkcja \u2013 linijka 34. Mo\u017cesz przeanalizowa\u0107 tak\u017ce jej definicj\u0119 w linijkach 16-17. Funkcja ta praktycznie nic nie robi. Mimo tego, jest bardzo rozwlek\u0142a. Czy uniform initialization i listy inicjalizacyjne mog\u0105 tu co\u015b pom\u00f3c? Zobaczmy.<\/p>\n<h3 class=\"western\">Wykorzystajmy uniform initializationn<\/h3>\n<p>Sp\u00f3jrz na poni\u017cszy kod. Nast\u0119pnie por\u00f3wnaj go z tym z poprzedniego akapitu i\u00a0wska\u017c r\u00f3\u017cnice.<\/p>\n<pre line=\"1\" lang=\"cpp\">\r\n#include <iostream>\r\n#include <vector>\r\n#include <utility>\r\nusing namespace std;\r\nstruct Foo {\r\n    int x;\r\n    float y;\r\n};\r\nclass Bar {\r\n    public:\r\n    Bar(int _x,float _y) : x(_x),y(_y) {}\r\n    private:\r\n    int x;\r\n    float y;\r\n};\r\npair<double,double> multiplyVectors(pair<double,double> v1,pair<double,double> v2) {\r\n    return {v1.first*v2.first,v1.second*v2.second};\r\n}\r\nint main()\r\n{\r\n    \/\/tworzenie obiekt\u00f3w za pomoc\u0105 konstruktora domy\u015blnego\r\n    Foo fooObject {};\r\n    \/\/tworzenie obiekt\u00f3w za pomoc\u0105 konstruktora w\u0142asnego\r\n    Foo FooObjectAggregate {3,3.5f};\r\n    Bar BarObjectWithConstructor{3,3.5f};\r\n\r\n    \/\/troch\u0119 zabawy z vectorami\r\n    vector<Bar> vectorOfBars {{1,1},{2,2},{3,3}};\r\n    auto result = multiplyVectors({2.0,2.0},{3.0,3.0});\r\n\r\n    \/\/Tablice\r\n    Foo arrOfFoos[] = {{1,1.0f},{2,2.0f},{3,3.0f}};\r\n    Bar arrOfBars[] = {{1,1.0f},{2,2.0f},{3,3.0f}};\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Zauwa\u017cy\u0142e\u015b pewnie, \u017ce jest o wiele pro\u015bciej. A przede wszystkim \u2013 bardziej jednolicie. Przeanalizujmy po kolei zmiany.<\/p>\n<p>Linijka 22 \u2013 tworzymy obiekt struktury Foo za pomoc\u0105 pustej listy inicjalizacyjnej. Dodatkowo, rozwi\u0105zuje nam to problem niejednoznaczno\u015bci. Pami\u0119tasz dylemat z poprzedniego przyk\u0142adu, gdzie zastanawiali\u015bmy si\u0119 czy mamy do czynienia ze zwyk\u0142\u0105 definicj\u0105 zmiennej czy deklaracj\u0105 funkcji? U\u017cywaj\u0105c uniform initialization, nie mamy takich dylemat\u00f3w. <\/p>\n<p>Linijka 24 i 25. Obydwa rodzaje \u2013 zar\u00f3wno struktur\u0119 jak i klas\u0119 z przeci\u0105\u017conym konstruktorem mo\u017cemy wype\u0142ni\u0107 tak samo \u2013 za pomoc\u0105 listy inicjalizacyjnej.<\/p>\n<p>Linijka 28. To tutaj najbardziej skr\u00f3cili\u015bmy kod. Nie ma ju\u017c wywo\u0142a\u0144 metody push_back. Wszystkie trzy elementy dodajemy w jednej linijce.<\/p>\n<p>Linijka 29. Tutaj r\u00f3wnie\u017c zauwa\u017cymy spore uproszczenie. Nie ma tego elementu kt\u00f3ry najbardziej wyd\u0142u\u017ca\u0142 nam t\u0119 linijk\u0119 \u2013 ci\u0105g\u0142ego powtarzania pair&lt;double,double&gt;. Wynik zwracany za pomoc\u0105 tej funkcji zapisujemy do zmiennej o typie auto. Dzi\u0119ki auto kompilator sam si\u0119 domy\u015bli, jakiego rodzaju zmienn\u0105 powinien utworzy\u0107. Natomiast w li\u015bcie argument\u00f3w u\u017cywamy listy inicjalizacyjnej do stworzenia obiekt\u00f3w pair i przekazania ich do funkcji.<\/p>\n<p>Zosta\u0142y nam tablice. No c\u00f3\u017c. Nie ma tutaj wiele do om\u00f3wienia. Nie wa\u017cne czy to struktura czy to klasa. Mo\u017cemy u\u017cy\u0107 nawias\u00f3w klamrowych do wype\u0142nienia jej warto\u015bciami. Kompilator sam domy\u015bli si\u0119, kt\u00f3rego konstruktora u\u017cy\u0107 w przypadku klasy.<\/p>\n<p>Zauwa\u017cy\u0142e\u015b gdzie jeszcze u\u017cy\u0142em uniform initialization? Sp\u00f3jrz na linijk\u0119 17. Zwracaj\u0105c wynik, nie tworzymy obiektu pair jawnie. Kreujemy go niejawnie, u\u017cywaj\u0105c listy inicjalizacyjnej. Dzi\u0119ki temu uzyskali\u015bmy znaczne skr\u00f3cenie zapisu.<\/p>\n<h2 class=\"western\">Uniform initialization &#8211; Niejednoznaczno\u015bci<\/h2>\n<p>Uniform Initialization czasami potrafi nam przysporzy\u0107 nieco problem\u00f3w. W przyk\u0142adzie analizowanym w poprzednim akapicie utworzyli\u015bmy klas\u0119 Bar. Mia\u0142a ona konstruktor przyjmuj\u0105cy dwa parametry. Jak zauwa\u017cy\u0142e\u015b, lista inicjalizacyjna korzysta\u0142a z tego konstruktora do stworzenia obiektu. Lecz nie zawsze tak jest.<\/p>\n<pre line=\"1\" lang=\"cpp\">\r\nvector<int> vec(400);\r\n<\/pre>\n<p>Sp\u00f3jrz na t\u0119 powy\u017csz\u0105, samotn\u0105 linijk\u0119 kodu. Zastan\u00f3w si\u0119 i odpowiedz na pytanie.<\/p>\n<p>Czy:<\/p>\n<ul>\n<li>doda do vectora vec warto\u015b\u0107 400?<\/li>\n<li>utworzy vector o wst\u0119pnym rozmiarze 400?<\/li>\n<\/ul>\n<p>Poprawn\u0105 odpowiedzi\u0105 jest odpowied\u017a druga. Lecz sp\u00f3jrz na to<\/p>\n<pre line=\"1\" lang=\"cpp\">\r\nvector<int> vec {400}\r\n<\/pre>\n<p>Co si\u0119 teraz stanie? Na podstawie przyk\u0142ad\u00f3w z poprzedniego akapitu odpowiesz, \u017ce teraz do vectora zostanie dodany element 400. Rzeczywi\u015bcie, listy inicjalizacyjne nie zawsze korzystaj\u0105 z konstruktor\u00f3w. A jak to wykorzysta\u0107?<\/p>\n<h2 class=\"western\">Lista inicjalizacyjna we w\u0142asnych klasach<\/h2>\n<p>Wiemy ju\u017c jak u\u017cywa\u0107 list inicjalizacyjnych. Dowiedzia\u0142e\u015b si\u0119, \u017ce domy\u015blnie lista inicjalizacyjna u\u017cywa konstruktora.Widzia\u0142e\u015b klas\u0119 vector?\u00a0Jak zrobi\u0107 we w\u0142asnej klasie tak\u0105 sztuczk\u0119, jak\u0105 stosuje vector? Nie jest to trudne. Sp\u00f3jrz na poni\u017cszy kod:<\/p>\n<pre line=\"1\" lang=\"cpp\">\r\n#include <iostream>\r\nusing namespace std;\r\nclass IFoo {\r\n    public:\r\n    IFoo(int a) {\r\n        this->x = a;\r\n        this->y = a;\r\n        this->z = a;\r\n    }\r\n    IFoo(initializer_list<int> l) {\r\n        initializer_list<int>::iterator i = l.begin();\r\n        if(i!=l.end()) {\r\n            x = *i;\r\n            i++;\r\n        }\r\n        if(i!=l.end()) {\r\n            y = *i;\r\n            i++;\r\n        }\r\n        if(i!=l.end()) {\r\n            z = *i;\r\n            i++;\r\n        }\r\n    }\r\n    void print() {\r\n        cout<<\"x: \"<<x<<\" y: \"<<y<<\" z: \"<<z<<endl;\r\n    }\r\n    private:\r\n    int x = 0;\r\n    int y = 0;\r\n    int z = 0;\r\n};\r\nint main()\r\n{\r\n    IFoo ob {1,2,3};\r\n    IFoo ob2 {1};\r\n    IFoo ob3(1);\r\n    cout<<\"ob: \";\r\n    ob.print();\r\n    cout<<\"ob2: \";\r\n    ob2.print();\r\n    cout<<\"ob3: \";\r\n    ob3.print();\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Naszym obiektem bada\u0144 sta\u0142a si\u0119 klasa IFoo. Mamy trzy sk\u0142adniki (zmienne) prywatne klasy: x,y,z. Konstruktor zadeklarowany i zdefiniowany w linijce 6 przypisuje t\u0119 sam\u0105 warto\u015b\u0107 wszystkim sk\u0142adnikom klasy. Gdyby\u015bmy nie dodawali obs\u0142ugi listy inicjacyjnej, to przy jej u\u017cyciu w\u0142a\u015bnie ten konstruktor by\u0142by wywo\u0142any.<\/p>\n<p>Ale my byli\u015bmy na tyle krn\u0105brni, \u017ce dodali\u015bmy do naszej klasy obs\u0142ug\u0119 listy inicjalizacyjnej. Ta obs\u0142uga to nic innego jak zwyk\u0142y konstruktor, kt\u00f3ry przyjmuje jako argument charakterystyczny parametr: <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/initializer_list\">initializer_list<\/a>. Pomimo skomplikowanego wygl\u0105du, nie jest to nic innego jak zwyk\u0142y kontener, po kt\u00f3rym mo\u017cemy si\u0119 porusza\u0107 za pomoc\u0105 iterator\u00f3w. Ten konstruktor, kt\u00f3ry zaczyna si\u0119 od linijki 11, przypisuje ka\u017cd\u0105 kolejno podan\u0105 liczb\u0119 kolejnym sk\u0142adnikom klasy.<\/p>\n<h2 class=\"western\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-390\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/11\/Screenshot_20181108_212249.png\" alt=\"efekt dzia\u0142ania ostatniego przyk\u0142adu\" width=\"350\" height=\"187\" \/><\/h2>\n<p>W funkcji main zaprezentowa\u0142em przyk\u0142ad u\u017cycia. Sp\u00f3jrz na wyj\u015bcie programu. W rezultacie wszystko powinno sta\u0107 si\u0119 dla ciebie jasne.<\/p>\n<h2 class=\"western\">Podsumowuj\u0105c \u2013 wady i zalety uniform initialization<\/h2>\n<p>Uniform initialization wprowadzony wraz z C++11 jest niezwykle przydatnym rozwi\u0105zaniem. Jego g\u0142\u00f3wn\u0105 zalet\u0105 jest skr\u00f3cenie kodu, co innymi s\u0142owy automatycznie poprawia jako\u015b\u0107 naszego kodu i pozwala na unikni\u0119cie pope\u0142niania b\u0142\u0119d\u00f3w. B\u0142\u0119d\u00f3w, kt\u00f3re mog\u0105 by\u0107 nieraz tragiczne w skutkach i spowodowa\u0107 wiele nieprzespanych nocy. Musimy jedynie uwa\u017ca\u0107 na pewne niejasno\u015bci, kiedy dana klasa jawnie m\u00f3wi jak b\u0119dzie interpretowa\u0107 list\u0119 inicjalizacyjn\u0105.<br \/>\nStandardowo, wszystkie kody \u017ar\u00f3d\u0142owe umieszczone w tym wpisie znajduj\u0105 si\u0119 w moim repozytorium na portalu GitHub <a href=\"https:\/\/github.com\/karol221-10\/blog_apps\/tree\/master\/uniform_initialization\">o, tutaj \ud83d\ude42 <\/a><br \/>\nJe\u015bli chcia\u0142by\u015b si\u0119 podzieli\u0107 swoj\u0105 opini\u0105, wal \u015bmia\u0142o \ud83d\ude42 <\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">&lt; 1<\/span> <span class=\"rt-label rt-postfix\">minut\u0119<\/span><\/span> Programuj\u0105c w C++, z pewno\u015bci\u0105 wiesz jak inicjuje si\u0119 zmienne. Nie jest to czynno\u015b\u0107 skomplikowana. Troch\u0119 wi\u0119cej problem\u00f3w zachodzi kiedy musisz zainicjowa\u0107 tablic\u0119 lub jaki\u015b kontener. Stosujesz wtedy pewnie p\u0119tl\u0119 &#8230;<\/p>\n","protected":false},"author":1,"featured_media":466,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[31],"tags":[],"_links":{"self":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/386"}],"collection":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/comments?post=386"}],"version-history":[{"count":14,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/386\/revisions"}],"predecessor-version":[{"id":403,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/386\/revisions\/403"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media\/466"}],"wp:attachment":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media?parent=386"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/categories?post=386"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/tags?post=386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}