abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    včera 14:44 | Nová verze

    Byla vydána verze 4.0.0 programovacího jazyka Ruby (Wikipedie). S Ruby Box a ZJIT. Ruby lze vyzkoušet na webové stránce TryRuby. U příležitosti 30. narozenin, první veřejná verze Ruby 0.95 byla oznámena 21. prosince 1995, proběhl redesign webových stránek.

    Ladislav Hagara | Komentářů: 0
    24.12. 02:11 | Komunita

    Všem čtenářkám a čtenářům AbcLinuxu krásné Vánoce.

    Ladislav Hagara | Komentářů: 20
    24.12. 02:00 | Nová verze

    Byla vydána nová verze 7.0 linuxové distribuce Parrot OS (Wikipedie). S kódovým názvem Echo. Jedná se o linuxovou distribuci založenou na Debianu a zaměřenou na penetrační testování, digitální forenzní analýzu, reverzní inženýrství, hacking, anonymitu nebo kryptografii. Přehled novinek v příspěvku na blogu.

    Ladislav Hagara | Komentářů: 0
    23.12. 18:33 | Nová verze

    Vývojáři postmarketOS vydali verzi 25.12 tohoto před osmi lety představeného operačního systému pro chytré telefony vycházejícího z optimalizovaného a nakonfigurovaného Alpine Linuxu s vlastními balíčky. Přehled novinek v příspěvku na blogu. Na výběr jsou 4 uživatelská rozhraní: GNOME Shell on Mobile, KDE Plasma Mobile, Phosh a Sxmo.

    Ladislav Hagara | Komentářů: 0
    23.12. 13:55 | Nová verze

    Byla vydána nová verze 0.41.0 multimediálního přehrávače mpv (Wikipedie) vycházejícího z přehrávačů MPlayer a mplayer2. Přehled novinek, změn a oprav na GitHubu. Požadován je FFmpeg 6.1 nebo novější a také libplacebo 6.338.2 nebo novější.

    Ladislav Hagara | Komentářů: 0
    23.12. 12:44 | Nová verze

    Byla vydána nová verze 5.5 (novinky) skriptovacího jazyka Lua (Wikipedie). Po pěti a půl letech od vydání verze 5.4.

    Ladislav Hagara | Komentářů: 0
    22.12. 23:44 | Nová verze

    Byla vydána nová verze 5.4.0 programu na úpravu digitálních fotografií darktable (Wikipedie). Z novinek lze vypíchnout vylepšenou podporu Waylandu. Nejnovější darktable by měl na Waylandu fungovat stejně dobře jako na X11.

    Ladislav Hagara | Komentářů: 0
    21.12. 05:00 | Nová verze

    Byla vydána beta verze Linux Mintu 22.3 s kódovým jménem Zena. Podrobnosti v přehledu novinek a poznámkách k vydání. Vypíchnout lze, že nástroj Systémová hlášení (System Reports) získal mnoho nových funkcí a byl přejmenován na Informace o systému (System Information). Linux Mint 22.3 bude podporován do roku 2029.

    Ladislav Hagara | Komentářů: 2
    21.12. 01:55 | Nová verze

    GNU Project Debugger aneb GDB byl vydán ve verzi 17.1. Podrobný přehled novinek v souboru NEWS.

    Ladislav Hagara | Komentářů: 0
    19.12. 17:22 | IT novinky

    Josef Průša oznámil zveřejnění kompletních CAD souborů rámů tiskáren Prusa CORE One a CORE One L. Nejsou vydány pod obecnou veřejnou licenci GNU ani Creative Commons ale pod novou licencí OCL neboli Open Community License. Ta nepovoluje prodávat kompletní tiskárny či remixy založené na těchto zdrojích.

    Ladislav Hagara | Komentářů: 14
    Kdo vám letos nadělí dárek?
     (34%)
     (2%)
     (10%)
     (2%)
     (1%)
     (2%)
     (16%)
     (18%)
     (14%)
    Celkem 88 hlasů
     Komentářů: 18, poslední 24.12. 15:30
    Rozcestník

    Dotaz: C++ shared_ptr - constrainty

    3.12.2020 01:45 mokere
    C++ shared_ptr - constrainty
    Přečteno: 561×
    Mám 2 pointery ukazujúce na 2 objekty (iterator a stream). Iterátor prechádza stream. Jeden z tých pointerov (iterator) vracia funkcia ReadLines. Ten druhý by sa mal uvolniť spolu s tým prvým. Ako na to? Skúmal som dokumentáciu a našiel som tam parameter konštruktora Deleter ktorý som využil na zmazanie oboch pointerov vo chcíli keď by sa mal zmazať smart pointer ukazujúci na iterator:
    namespace
    {
    	template<typename CharType = wchar_t>
    	std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& inputStream, std::basic_string<CharType>& line)
    	{
    		std::getline(inputStream, line);
    		return inputStream;
    	}
    }
    
    template<typename CharType = char>
    auto ReadLines(std::wstring path)
    {
    	auto inputStream = new std::ifstream(path);
    	using iterator = std::istream_iterator<std::basic_string<CharType>>;
    	auto begin = std::shared_ptr<iterator>(
    		new iterator(*inputStream),
    		[inputStream](auto* iterator)
    		{
    			delete iterator;
    			delete inputStream;
    		}
    	);
    	return begin;
    }
    Je toto správne riešenie? Alebo na to idem zle? Lebo fungovať mi to funguje. Ak viete o niečom priamočiarejšom tak sem s tým. Ďakujem.

    Odpovědi

    3.12.2020 01:53 mokere
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty
    A takto sa potom volá funkcia ReadLines:
    auto begin = ReadLines(L"c:\test\newFile21.txt");
    for (auto it = *begin; it != std::istream_iterator<std::string>(); ++it)
    {
    	std::cout << ":" << *it << "n";
    }
    3.12.2020 01:56 mokere
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty
    nejako blbne escapovanie, namiesto n tam malo byť lomitko a n resp std::endl
    3.12.2020 09:20 MadCatX | skóre: 28 | blog: dev_urandom
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty
    #include <fstream>
    #include <iostream>
    #include <stdexcept>
    
    template <typename T>
    void read_lines(const std::string &path, T &&handler)
    {
            std::ifstream s{};
            s.open(path);
            if (!s.is_open())
                    throw std::runtime_error{"Cannot open file"};
    
            std::string str{};
            while (std::getline(s, str).good())
                    handler(str);
    }
    
    int main()
    {
            try {
                    read_lines("abc.txt", [](const std::string &s) { std::cout << s << std::endl; });
            } catch (const std::runtime_error &ex) {
                    std::cout << ex.what() << std::endl;
            }
    
            return 0;
    }
    
    3.12.2020 10:50 10minuteman
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty
    Obecne, jak mas nekde nahe new & delete, vis, ze to nepises dobre. Spravne je vyuzit RAII a vytvorit si nejakou guard tridu: new volas v konstruktoru, delete v destruktoru. Pak mas jistotu, ze se spravne uvolni tvuj resource i pri nestandardnim ukonceni scope (treba pri vyhozeni vyjimky). No ale jelikoz std typy tak uz funguji (tedy svuj resource si hlida uz treba ten ifstream), nemusis to nijak resit a napis to tak, jak ti radi MadCatX.

    Za druhe, std::shared_ptr (a podobne veci) inicializuj pomoci std::make_shared (a podobnych funkci) - je to bezpecnejsi a rychlejsi.
    3.12.2020 19:07 Andrej | skóre: 51 | blog: Republic of Mordor
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty

    Začal bych od jednoduchého příkladu — implicitní iterace po slovech. To se zařídí třeba takhle:

    #include <fstream>
    #include <iostream>
    #include <iterator>
    #include <string>
    
    namespace {
    
    template<typename C>
    struct ifstream_iterable {
      ifstream_iterable(const std::string &path) : stream_{path} {}
      auto begin() { return iterator{stream_}; }
      auto end() { return iterator{}; }
     private:
      typedef std::istream_iterator<std::basic_string<C>, C> iterator;
      std::basic_ifstream<C> stream_;
    };
    
    }  // namespace
    
    int main() {
      for (auto &w : ifstream_iterable<wchar_t>{"/proc/cpuinfo"})
        std::wcout << w << std::endl;
    }
    

    To bychom měli. Teď je otázka, jak z toho^^^ udělat iteraci po řádcích. Předně pár poznámek k tématu:

    • Tvůj příklad s operátorem >> je mírně špatně v mezích zákona, protože deklarace je hodně podobná této deklaraci v headeru <string>, což sice na první pohled nevadí, ale na druhý pohled tam hraje roli až příliš mnoho složitých detailů kolem pravidel pro hledání identifikátorů. Drobná změna standardu a/nebo (kni)hovny může vést k tomu, že operátor se buď vůbec nepoužije, nebo začne být v konfliktu s operátory z (kni)hovny. Drobnou modifikací se mi podařilo vyrobit (proti)příklad, kdy clang++ i g++ kód přeloží bez varování, ale g++ „přetížený“ operátor použije, zatímco clang++ nikoliv.
    • Jedno (nechvalně) známé řešení ze Zásobníkovéhopřetečení sice vypadá na první pohled hezky a jednoduše, ale vyskytují se v něm tři poněkud nepříjemné a sporné nápady:

      • soukromá dědičnost (která se tu a tam hodí, ale tenhle případ není ani tu, ani tam)
      • kámoši (kterým je ideální se vyhnout, protože všeho všudy ukazují na chybu v návrhu (zapouzdření atd.))
      • dědění od std::string (což je sice technicky možné, ale z hlediska kompatibility a udržovatelnosti kódu je vhodné se takových nápadů vyvarovat)

    Co tedy podniknout? Třeba tohle:

    #include <fstream>
    #include <iostream>
    #include <iterator>
    #include <string>
    #include <utility>
    
    namespace {
    
    template <typename C>
    struct line {
      std::basic_istream<C>& operator <<(std::basic_istream<C> &stream) {
        std::getline(stream, str_);
        return stream;
      }
      operator const std::basic_string<C>&() const & { return str_; }
      operator std::basic_string<C>&() & { return str_; }  // zde se nepoužije
      operator std::basic_string<C>() && { return std::move(str_); }  // -dtto-
     private:
      std::basic_string<C> str_;
    };
    
    template <typename C>
    std::basic_istream<C>& operator >>(std::basic_istream<C> &stream,
                                       line<C> &str) {
      str << stream;
      return stream;
    }
    
    template<typename C>
    struct ifstream_iterable {
      ifstream_iterable(const std::string &path) : stream_{path} {}
      auto begin() { return iterator{stream_}; }
      auto end() { return iterator{}; }
     private:
      typedef std::istream_iterator<line<C>, C> iterator;
      std::basic_ifstream<C> stream_;
    };
    
    }  // namespace
    
    int main() {
      for (const std::wstring &l : ifstream_iterable<wchar_t>{"/proc/cpuinfo"})
        std::wcout << l << std::endl;
    }
    

    Tohle^^^ nedědí od základních typů, nevyvolává příliš mnoho nespecifikovaných rohových případů, nepoužívá kámoše a vystačí si s jednou třídou (dělnickou), kterou lze konvertovat na odpovídající string. (Pro složitější konverze do jiného API si lze napsat deduction guides, ale to už je jiné téma. V této podobě se kód přeloží s C++ 14, 17 i 20, zatímco s deduction guides by vyžadoval minimálně C++17.)

    Ještě závěrem dodám (a předejdu tak, doufám, některým komentářům), že někteří lidé mají utkvělou špatnou představu o sousloví return std::move(...); — myslí si, že něco takového nedává smysl a že by to nemělo existovat. Samozřejmě se mýlí, jak jinak; tady jsou k tomu předdrobnosti i podrobnosti.

    3.12.2020 19:17 Andrej | skóre: 51 | blog: Republic of Mordor
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty

    A když nad tím znova přemýšlím (což rozhodně nedělám často), čitelnější to bude bez toho nestandardního operátoru <<, který nijak neinteraguje s (kni)hovnou a jenom všeho všudy mate čtenáře (včetně mě). Takže raději třeba takto:

    #include <fstream>
    #include <iostream>
    #include <iterator>
    #include <string>
    #include <utility>
    
    namespace {
    
    template <typename C>
    struct line {
      operator const std::basic_string<C>&() const & { return str_; }
      operator std::basic_string<C>&() & { return str_; }
      operator std::basic_string<C>() && { return std::move(str_); }  // nepoužito
     private:
      std::basic_string<C> str_;
    };
    
    template <typename C>
    std::basic_istream<C>& operator >>(std::basic_istream<C> &stream,
                                       line<C> &str) {
      std::getline(stream, static_cast<std::basic_string<C>&>(str));
      return stream;
    }
    
    template<typename C>
    struct ifstream_iterable {
      ifstream_iterable(const std::string &path) : stream_{path} {}
      auto begin() { return iterator{stream_}; }
      auto end() { return iterator{}; }
     private:
      typedef std::istream_iterator<line<C>, C> iterator;
      std::basic_ifstream<C> stream_;
    };
    
    }  // namespace
    
    int main() {
      for (const std::wstring &l : ifstream_iterable<wchar_t>{"/proc/cpuinfo"})
        std::wcout << l << std::endl;
    }
    
    5.12.2020 17:07 mokere
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty
    Ďakujem Vám všetkým. Aj za to že ste mi opravili chybu s riadkami vs slovami. To bola moja nepozornosť. A popravde som si ju ani nevšimol.

    Každopádne MadCatX to vymyslel zaujímavo.

    Ja som chcel ale napodobniť funkciu ReadLines z .NETu https://docs.microsoft.com/en-us/dotnet/api/system.io.file.readlines?view=net-5.0 ktorá vracia IEnumerable (obsahujúca Enumerator).

    Andrej To čo ste urobili vy je presne to čo som hľadal. Za čo Vám veľmi pekne ďakujem.

    10minuteman Čo sa týka new a delete snažím sa ich používať minimálne. Ale ak pri smartpointeroch používate deleter tak sa použitiu delete nevyhnete. Veď aj smart pointery v konečnom dôsledku volajú delete.

    5.12.2020 22:17 Andrej | skóre: 51 | blog: Republic of Mordor
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty
    Ale ak pri smartpointeroch používate deleter tak sa použitiu delete nevyhnete.

    To je sice pravda, ale právě nadužívání dynamické alokace je u C++ poměrně častá chyba. Zrovna třeba statement delete iterator; není dobrý nápad (a kdekoho přiměje zvednout obočí), protože iterátor má být (a většinou je) malý kousek dat (něco jako 16 B, dejme tomu), který se dá a má předávat všude hodnotou. (Samozřejmě kromě případu, kdy je potřeba z více míst měnit jeden iterátor, tj. mít něco jako dvouhvězdičkový pointer.)

    Ještě bych poznamenal, jen tak pro úplnost, že příklad v dotazu by byl lepší s použitím std::unique_ptr místo std::shared_ptr. Zatímco std::unique_ptr je jednoduchý zapouzdřený pointer, který vyjadřuje exkluzivní vlastnictví a vlastní z jednoho kontextu jeden kousek dat, std::shared_ptr je složitá mašinerie s atomickým reference-countingem. Uvnitř v implementaci std::shared_ptr neukazuje přímo na data, která spravuje, nýbrž na svou vlastní dynamickou strukturu, ve které má (kromě pointeru) také atomické počítadlo referencí a pár dalších vychytávek. (Dlužno navíc dodat, v souvislosti s atomickým počítadlem, že jedna atomická instrukce může stát čas srovnatelný s řádově tisícem sčítání.) Dá se říct, že std::shared_ptr je v jistém smyslu thread-safe, byť s omezeními:

    • Několik instancí std::shared_ptr, každou z jiného vlákna, lze používat paralelně zcela bez omezení.
    • Použití jedné instance std::shared_ptr několika vlákny (například rozumně atomické přiřazení toho sdíleného pointeru) ovšem samo od sebe atomické není; k tomu slouží specializace std::atomic<std::shared_ptr<...>>.

    Zkrátka a dobře (nebo zdlouha a špatně, teď nevím),

    • kdykoliv je možné vyhnout se přímému použití pointerů, je třeba této příležitosti využít. Všechny kontejnery mají na zásobníku jenom něco velmi malého (jako třeba fixních 16 B nebo tak) a dynamickou alokaci si spravují samy.
    • kdykoliv je možné použít std::unique_ptr místo std::shared_ptr, je to jasná volba, zejména z hlediska efektivity a jednoznačnosti vlastnictví objektů. Atomický reference-counting je potřebný jenom velmi zřídka, nikoliv zhusta.
    6.12.2020 15:21 10minuteman
    Rozbalit Rozbalit vše Re: C++ shared_ptr - constrainty
    No to je prave ono: nepsat to rucne, ale nechat to za sebe resit objekty. Jasne, ze interne k new a delete treba dojde. Alokaci na halde se nejspis nevyhnes. Kdyz to ale za tebe bude resit objekt, mas pak mnohem mene starosti.

    Založit nové vláknoNahoru

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.