Понимание эффективности std :: string - PullRequest
6 голосов
/ 24 апреля 2011

Я пытаюсь узнать немного больше о строках c ++.

рассмотреть

const char* cstring = "hello";
std::string string(cstring);

и

std::string string("hello");

Правильно ли я полагаю, что и хранилище "hello" в разделе .data приложения, и байты затем копируются в другую область в куче, где указатель, управляемый std :: string, может получить к ним доступ?

Как я могу эффективно хранить действительно очень длинную строку? Я вроде думаю о приложении, которое читает данные из потока сокетов. Я боюсь объединяться много раз. Я мог бы представить себе использование связанного списка и просмотреть этот список.

Струны запугивали меня слишком долго!

Любые ссылки, советы, объяснения, дальнейшие подробности были бы чрезвычайно полезны.

Ответы [ 4 ]

2 голосов
/ 24 апреля 2011

Поскольку вы читаете строку из сокета, вы можете повторно использовать одни и те же буферы пакетов и связать их вместе, чтобы представить огромную строку. Это позволит избежать ненужного копирования и, вероятно, является наиболее эффективным решением. Кажется, я помню, что библиотека ACE обеспечивает такой механизм. Я постараюсь найти его.

РЕДАКТИРОВАТЬ: ACE имеет ACE_Message_Block, который позволяет хранить большие сообщения в виде связанных списков. Вам почти нужно прочитать книги по сетевому программированию на C ++, чтобы разобраться в этой колоссальной библиотеке. Бесплатные учебники на сайте ACE действительно отстой.

Бьюсь об заклад, Boost.Asio должен быть способен делать то же самое, что и блоки сообщений ACE. Похоже, что Boost.Asio теперь имеет больший кругозор, чем ACE, поэтому я предлагаю сначала поискать решение в Boost.Asio. Если кто-нибудь сможет рассказать нам о решении Boost.Asio, это было бы здорово!


Пора попробовать написать простое клиент-серверное приложение, используя Boost.Asio, чтобы понять, о чем идет речь.

2 голосов
/ 24 апреля 2011

Я сохранил строки в диапазоне 10 или 100 МБ без проблем.Естественно, оно будет в первую очередь ограничено вашей доступной (непрерывной) памятью / адресным пространством.

Если вы собираетесь добавлять / объединять, есть несколько вещей, которые могут помочь с точки зрения эффективности: если возможно, попробуйтеиспользование функции-члена reserve () для предварительного выделения пространства - даже если у вас есть приблизительное представление о том, каким может быть конечный размер, это избавит от ненужных перераспределений по мере роста строки.

Кроме того, во многих реализациях строк используется «экспоненциальный рост», что означает, что они увеличиваются на некоторый процент , а не на фиксированный размер в байтах.Например, он может просто удвоить емкость каждый раз, когда требуется дополнительное пространство.Увеличивая размер экспоненциально, становится более эффективным выполнять множество конкатенаций.(Точные детали будут зависеть от вашей версии stl.)

Наконец, другой вариант (если ваша библиотека поддерживает это) - использовать шаблон веревка <> : Канаты похожи на строки,за исключением того, что они намного более эффективны при выполнении операций с очень большими строками.В частности, «веревки распределяются небольшими порциями, что значительно уменьшает проблемы фрагментации памяти, создаваемые большими блоками».Некоторые дополнительные сведения о Руководстве SGI по STL .

0 голосов
/ 24 апреля 2011

Как вы, наверное, знаете, и std::string - это просто другое имя для basic_string<char>.

Тем не менее, они представляют собой контейнер последовательности, и память будет выделяться последовательно. Исключения можно получить из std :: string, если вы попытаетесь сделать единицу больше, чем доступная непрерывная память, которую вы можете выделить. Этот порог обычно значительно меньше общего объема доступной памяти из-за фрагментации памяти.

Я видел проблемы с выделением смежной памяти при попытке выделить, например, большие смежные 3D-буферы для изображений. Но эти проблемы не начинаются, по крайней мере, порядка 100 МБ или около того, по крайней мере, по моему опыту, в Windows XP Pro (например).

Твои струны такие большие?

0 голосов
/ 24 апреля 2011

Я не думаю, что эффективность должна быть проблемой. Оба будут работать достаточно хорошо.

Решающим фактором здесь является инкапсуляция. std::string - намного лучшая абстракция, чем char *. Инкапсулирующая арифметика указателей - это хорошо.

Многие люди думали долго и трудно придумать std::string. Я думаю, что не использовать его по необоснованным причинам эффективности глупо. Придерживайтесь лучшей абстракции и инкапсуляции.

...