"Właściwy" sposób przechowywania danych binarnych w C++ / STL

Ogólnie, jaki jest najlepszy sposób przechowywania danych binarnych w C++? Opcje, o ile mogę powiedzieć, sprowadzają się do używania łańcuchów lub wektorowych s. (pominę możliwość char*s i malloc () s, ponieważ mam na myśli konkretnie C++).

Zazwyczaj używam tylko ciągu znaków, jednak nie jestem pewien, czy brakuje mi ogólnych kosztów, czy konwersji, które STL robi wewnętrznie, które mogłyby namieszać w rozsądku danych binarnych. Czy ktoś ma jakieś wskazówki (har) na ten temat? Sugestie lub preferencje w ten czy inny sposób?

Author: Sean Edwards, 2009-01-14

4 answers

Wektor char jest ładny, ponieważ pamięć jest przylegająca. Dlatego możesz go używać z wieloma API C, takimi jak gniazda berkley lub API plików. Możesz wykonać następujące czynności, na przykład:

  std::vector<char> vect;
  ...
  send(sock, &vect[0], vect.size());

I będzie działać dobrze.

Można traktować go jak każdy inny dynamicznie przydzielany bufor znaków. Możesz skanować w górę iw dół w poszukiwaniu magicznych liczb lub wzorów. Możesz go częściowo przeanalizować. Do odbioru z gniazda można bardzo łatwo zmienić jego rozmiar, aby dołączyć więcej data.

Minusem jest to, że zmiana rozmiaru nie jest zbyt wydajna (zmiana rozmiaru lub prealokacja), a usunięcie z przodu tablicy również będzie bardzo nieefektywne. Jeśli chcesz, powiedzmy, pop tylko jeden lub dwa znaki na raz z przodu struktury danych bardzo często, kopiowanie do deque przed tym przetwarzaniem może być opcją. To kosztuje kopię i pamięć deque nie jest przylegająca, więc nie można po prostu przekazać wskaźnika do C API.

Podsumowując, poznaj dane struktury i ich tradeoffs przed nurkowaniem, jednak wektor char jest zazwyczaj to, co widzę stosowane w praktyce ogólnej.

 39
Author: Doug T.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-13 23:11:12

Największy problem z std:: string polega na tym, że obecny standard nie gwarantuje, że jego podstawowa pamięć jest ciągła. Nie są jednak znane implementacje STL, w których string nie jest ciągiem ciągłym, więc w praktyce prawdopodobnie nie zawiedzie. W rzeczywistości nowy standard C++0x naprawi ten problem, nakazując, aby std:: string używał sąsiadującego bufora, takiego jak std:: vector.

Innym argumentem przeciwko string jest to, że jego nazwa sugeruje, że zawiera łańcuch znaków, nie jest to bufor binarny, co może powodować zamieszanie u osób, które czytają kod.

To powiedziawszy, polecam również vector.

 8
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-14 02:31:17

Do tego też używam std::string i nigdy nie miałem z tym problemu.

Jeden "wskaźnik", o którym wczoraj otrzymałem ostre przypomnienie w kawałku kodu: tworząc łańcuch z bloku danych binarnych, użyj konstruktora std::string(startIter, endIter), a nie std::string(ptr, offset, length) -- ten ostatni zakłada, że wskaźnik wskazuje na łańcuch w stylu C i ignoruje wszystko po pierwszym znaku zero (kopiuje "do" podanych length, a nie length znaków).

 6
Author: Head Geek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-14 02:10:57

Z pewnością powinieneś używać jakiegoś kontenera char, ale kontener, którego chcesz użyć, zależy od twojej aplikacji.

Znaki mają kilka właściwości, które czynią je użytecznymi do przechowywania danych binarnych: standard wyłącza jakiekolwiek "wypełnienie" dla typu danych char, co jest ważne, ponieważ oznacza to, że nie otrzymasz śmieci w układzie binarnym. Każdy znak jest również gwarantowany jako dokładnie jeden bajt, co czyni go jedynym zwykłym starym typem danych (POD) o ustawionej szerokości (wszystkie pozostałe są określone w warunki górnej i / lub dolnej granicy).

Dyskusja na temat odpowiedniego kontenera stl, za pomocą którego można przechowywać znaki jest obsługiwana przez well przez Douga powyżej. To, którego potrzebujesz, zależy wyłącznie od Twojego przypadku użycia. Jeśli po prostu trzymasz blok danych, które iterujesz, bez specjalnego wyszukiwania, dodawania/usuwania lub potrzeby splicingu, wolałbym vector, który sprawia, że twoje intencje są bardziej jasne niż std:: string, który wiele bibliotek i funkcji przyjmie, że zawiera zakończony znakiem null styl c sznurek.

 3
Author: Todd Gardner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-14 02:18:18