Jaka jest różnica między istringstream, ostringstream i stringstream? / Dlaczego nie używać stringstream w każdym przypadku?

163

Kiedy używam std::istringstream, std::ostringstreami std::stringstreamdlaczego nie należy po prostu użyć std::stringstreamw każdej sytuacji (czy są jakieś problemy z wydajnością Runtime?).

Wreszcie, czy jest w tym coś złego (zamiast w ogóle korzystać ze strumienia):

std::string stHehe("Hello ");

stHehe += "stackoverflow.com";
stHehe += "!";
Oliver Baur
źródło

Odpowiedzi:

119

Osobiście uważam, że bardzo rzadko chcę przesyłać strumieniowo do i z tego samego strumienia struny.

Zwykle chcę zainicjować strumień z łańcucha, a następnie go przeanalizować; lub przesyłaj strumieniowo rzeczy do strumienia łańcuchowego, a następnie wyodrębnij wynik i zapisz go.

Jeśli przesyłasz strumieniowo do iz tego samego strumienia, musisz bardzo uważać na stan i pozycje strumienia.

Korzystanie z „tylko” istringstreamlub ostringstreamlepiej wyraża swoją intencją i daje pewne sprawdzone przeciwko głupich błędów takich jak przypadkowe wykorzystania <<vs >>.

Tam może być jakiś wzrost wydajności, ale nie będę patrzeć na to jako pierwszy.

Nie ma nic złego w tym, co napisałeś. Jeśli okaże się, że nie działa wystarczająco dobrze, możesz profilować inne podejścia, w przeciwnym razie trzymaj się tego, co jest najwyraźniejsze. Osobiście wybrałbym po prostu:

std::string stHehe( "Hello stackoverflow.com!" );
CB Bailey
źródło
22

A stringstreamjest nieco większy i może mieć nieco niższą wydajność - dziedziczenie wielokrotne może wymagać dostosowania wskaźnika vtable. Główną różnicą jest (przynajmniej w teorii) lepsze wyrażanie zamiarów i zapobieganie przypadkowemu użyciu >>tam, gdzie zamierzałeś <<(lub odwrotnie). OTOH, różnica jest na tyle mała, że ​​szczególnie przy szybkich fragmentach kodu demonstracyjnego i tym podobnych, jestem leniwy i po prostu używam stringstream. Nie mogę sobie przypomnieć, kiedy ostatni raz przypadkowo używany <<gdy zamierzałem >>, więc mi się, że trochę bezpieczeństwa wydaje głównie teoretyczny (zwłaszcza jeśli zrobić zrobić taki błąd, to będzie niemal zawsze być naprawdę oczywisty niemal natychmiast).

Nie ma nic złego w zwykłym używaniu sznurka, o ile spełnia on to, czego chcesz. Jeśli po prostu składasz struny, jest to łatwe i działa dobrze. Jeśli jednak chcesz sformatować inne rodzaje danych, a stringstreambędzie to obsługiwać, a ciąg w większości nie.

Jerry Coffin
źródło
17

W większości przypadków nie będziesz potrzebować zarówno danych wejściowych, jak i wyjściowych w tym samym strumieniu łańcuchów, więc użycie std::ostringstreami std::istringstreamjawnie wyjaśnia swój zamiar. Zapobiega również przypadkowemu wpisaniu niewłaściwego operatora ( <<vs>> ).

Gdy musisz wykonać obie operacje na tym samym strumieniu, oczywiście użyjesz wersji ogólnego przeznaczenia.

Problemy z wydajnością byłyby tutaj najmniejszym z Twoich zmartwień, przejrzystość jest główną zaletą.

Wreszcie nie ma nic złego w używaniu dodawania ciągów, ponieważ musisz konstruować czyste łańcuchy. Po prostu nie możesz tego używać do łączenia liczb, tak jak w językach takich jak perl.

Mark B.
źródło
8

istringstream służy do wejścia, ostringstream do wyjścia. stringstream to wejście i wyjście. Strumienia ciągów można używać praktycznie wszędzie. Jeśli jednak oddasz swój obiekt innemu użytkownikowi i użyje on operatora >> podczas gdy ty czekasz na obiekt tylko do zapisu, nie będziesz zadowolony ;-)

PS: nic złego w tym, tylko problemy z wydajnością.

Scharron
źródło
2

Odpowiadając na trzecie pytanie: Nie, to całkiem rozsądne. Zaletą używania strumieni jest to, że możesz wprowadzić dowolny rodzaj wartości, który ma operator<<zdefiniowaną, podczas gdy możesz dodawać tylko ciągi (C ++ lub C) do pliku std::string.

David Thornley
źródło
1

Przypuszczalnie, gdy tylko wstawianie lub tylko wyodrębnianie jest odpowiednie dla twojej operacji, możesz użyć jednej z wersji z prefiksem „i” lub „o”, aby wykluczyć niechcianą operację.

Jeśli to nie jest ważne, możesz użyć wersji I / O.

Pokazana konkatenacja ciągów jest całkowicie poprawna. Chociaż możliwe jest połączenie za pomocą stringstream, nie jest to najbardziej użyteczną cechą stringstreams, która polega na możliwości wstawiania i wyodrębniania POD i abstrakcyjnych typów danych.

Amardeep AC9MF
źródło
1

std :: ostringstream :: str () tworzy kopię zawartości strumienia, co w niektórych sytuacjach podwaja użycie pamięci. Zamiast tego możesz użyć std :: stringstream i jego funkcji rdbuf (), aby tego uniknąć.

Więcej szczegółów tutaj: jak napisać ostringstream bezpośrednio do cout

Gerhard Wesp
źródło
0

Po co otwierać plik do odczytu / zapisu, jeśli na przykład chcesz tylko z niego odczytać?

Co się stanie, jeśli do odczytu z tego samego pliku potrzeba wielu procesów?

Assaf Lavie
źródło