Подтвердить что ты не робот

Неизменяемые строки vs std::string

Недавно я читал о неизменяемых строках, здесь и здесь, а также о том, почему D выбрал неизменяемые строки. Кажется, что есть много преимуществ.

  • тривиально безопасный поток
  • более безопасный
  • больше памяти в большинстве случаев использования.
  • дешевые подстроки (токенизация и нарезка)

Не говоря уже о том, что большинство новых языков имеют неизменяемые строки, D2.0, Java, С#, Python и т.д.

Может ли С++ извлечь выгоду из неизменяемых строк?

Возможно ли реализовать неизменяемый строковый класс в С++ (или С++ 0x), который будет иметь все эти преимущества?


обновление:

Есть две попытки в неизменяемых строках const_string и fix_str. Ни то, ни другое не было обновлено через полвека. Они даже используются? Почему const_string никогда не превращал его в boost?

4b9b3361

Ответ 1

Как мнение:

  • Да, мне бы очень понравилась неизменяемая строковая библиотека для С++.
  • Нет, мне бы не хотелось, чтобы std::string был неизменным.

Действительно ли это стоит (как стандартная функция библиотеки)? Я бы сказал, нет. Использование константы дает вам неизменяемые строки, а основной характер языков системного программирования означает, что вам действительно нужны изменяемые строки.

Ответ 2

Я нашел, что большинство людей в этом потоке не понимают, что такое immutable_string. Речь идет не только о постоянной. На самом деле сила immutable_string - это производительность (даже в программе с одним потоком) и использование памяти.

Представьте, что если все строки являются неизменяемыми, а вся строка реализована как

class string {
    char* _head ;
    size_t _len ;
} ;

Как мы можем реализовать операцию подстроки? Нам не нужно копировать любые char. Все, что нам нужно сделать, это назначить _head и _len. Затем подстрока разделяет один и тот же сегмент памяти с исходной строкой.

Конечно, мы не можем реализовать immutable_string только с двумя членами данных. Реальной реализации может потребоваться блок памяти с подсчетом отсчета (или взвешенной по взвешиванию). Как этот

class immutable_string {
    boost::fly_weight<std::string> _s ;
    char* _head ;
    size_t _len ;
} ;

В большинстве случаев память и производительность будут лучше, чем традиционная строка, особенно когда вы знаете, что делаете.

Конечно, С++ может извлечь выгоду из неизменяемой строки, и хорошо иметь ее. Я проверил boost::const_string и fix_str, упомянутые Cubbi. Это должно быть то, о чем я говорю.

Ответ 3

Мое заключение состоит в том, что С++ не требует неизменяемого шаблона, поскольку имеет семантику const.

В Java, если у вас есть класс Person, и вы возвращаете String name человека с помощью метода getName(), ваша единственная защита - неизменяемый шаблон. Если бы он не был там, вы должны были бы clone() ваши строки всю ночь и день (как вы должны делать с членами данных, которые не являются типичными объектами значений, но все равно должны быть защищены).

В С++ у вас есть const std::string& getName() const. Поэтому вы можете написать SomeFunction(person.getName()), где он похож на void SomeFunction(const std::string& subject).

  • Не удалось выполнить копию
  • Если кто-то хочет скопировать, он может это сделать
  • Техника применяется ко всем типам данных, а не только к строкам

Ответ 4

Я не думаю, что здесь есть окончательный ответ. Это субъективно, если не потому, что личный вкус, по крайней мере, из-за типа кода, который чаще всего имеет дело. (Тем не менее, ценный вопрос.)

Неизменяемые строки великолепны, когда память дешевая - это было неверно, когда С++ был разработан, и это не относится ко всем платформам, ориентированным на С++. (OTOH на более ограниченных платформах C кажется гораздо более распространенным, чем С++, поэтому аргумент слабый.)

Вы можете создать неизменяемый строковый класс на С++, и вы можете сделать его в значительной степени совместимым с std::string — но вы все равно проиграете по сравнению со встроенным строковым классом с выделенными оптимизациями и языковыми функциями.

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

Ответ 5

Ты, конечно, не единственный человек, который хоть и это. Фактически существует библиотека const_string, которую Максим Егорушкин, похоже, был написан с включением в импульс. И здесь немного новая библиотека, fix_str от Roland Pibinger. Я не уверен, насколько сложным будет полное вмешательство во время выполнения, но большинство преимуществ достижимы, когда это необходимо.

Ответ 6

const std::string

Там вы идете. Строковый литерал также является неизменным, если вы не хотите входить в поведение undefined.

Изменить: Конечно, это только половина истории. Строковая переменная const не полезна, потому что вы не можете ссылаться на новую строку. Ссылка на строку const будет делать это, за исключением того, что С++ не позволит вам переназначить ссылку, как на других языках, таких как Python. Самое близкое было бы умным указателем на динамически выделенную строку.

Ответ 7

Неизменяемые строки великолепны, если, когда это необходимо для создания новой строки, диспетчер памяти всегда сможет определить, где находится каждая строка ссылки. На большинстве платформ языковая поддержка таких возможностей может предоставляться по относительно скромной цене, но на платформах без такой языковой поддержки, встроенных в нее, намного сложнее.

Если, например, нужно было спроектировать реализацию Pascal на x86, поддерживающую неизменяемые строки, необходимо, чтобы распределитель строк мог ходить по стеку, чтобы найти все ссылки на строки; единственная стоимость выполнения этого времени потребует последовательного подхода к функциональному вызову (например, не используя хвостовые вызовы, и каждая функция не-листа поддерживает указатель кадра]. Каждая область памяти, выделенная с помощью new, должна иметь бит, чтобы указать, содержит ли она какие-либо строки, а те, которые содержат строки, должны иметь индекс для дескриптора макета памяти, но эти затраты будут незначительными.

Если GC не был таблицей для перехода к стеку, тогда необходимо было бы использовать дескрипторы использования кода, а не указатели, и иметь код, создающий строковые дескрипторы, когда локальные переменные попадают в область видимости и уничтожают дескрипторы, когда они выходят объема. Значительно большие издержки.

Ответ 8

Qt также использует неизменяемые строки с копированием на запись.
Существует некоторая дискуссия о том, сколько производительности она действительно покупает у вас с достойными компиляторами.

Ответ 9

константные строки не имеют смысла в семантике значений, а совместное использование не является одной из сильных сторон С++...

Ответ 10

Строки изменяются в Ruby.

$ irb
>> foo="hello"
=> "hello"
>> bar=foo
=> "hello"
>> foo << "world"
=> "helloworld"
>> print bar
helloworld=> nil
  • тривиально безопасный поток

Я хотел бы забыть аргументы в пользу безопасности. Если вы хотите быть потокобезопасным, заблокируйте его или не прикасайтесь к нему. С++ не является удобным языком, имеет свои собственные соглашения.

  • более безопасный

Нет. Как только у вас будет указательная арифметика и незащищенный доступ к адресному пространству, забудьте о безопасности. Безопаснее против невинно плохого кодирования, да.

  • больше памяти в большинстве случаев использования.

Если вы не реализуете механизмы, интенсивно использующие CPU, я не вижу, как это сделать.

  • дешевые подстроки (токенизация и нарезка)

Это будет очень хороший момент. Может быть сделано путем ссылки на строку с обратными ссылками, где изменения в строке вызовут копию. Токенизация и нарезка становятся свободными, мутации становятся дорогими.

Ответ 11

Строки С++ являются потокобезопасными, все неизменяемые объекты гарантируются потокобезопасностью, но Java StringBuffer является изменяемым, как и строка С++, и обе они являются потокобезопасными. Зачем беспокоиться о скорости, определить свой метод или параметры функции с помощью ключевого слова const, чтобы сообщить компилятору, что строка будет неизменной в этой области. Также, если строковый объект является неизменным по требованию, ожидая, когда вам абсолютно необходимо использовать строку, другими словами, когда вы добавляете другие строки в основную строку, у вас есть список строк, пока вам не понадобится целая строка, тогда они будут объединены вместе в этой точке.

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