неизменяемые строки против std :: string - PullRequest
61 голосов
/ 27 мая 2010

Я недавно читал о неизменяемых строках Почему строки не могут быть изменяемыми в Java и .NET? и Почему .NET String является неизменяемой? , а также некоторые вещи о почему D выбрал неизменные строки. Кажется, есть много преимуществ.

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

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

Получит ли C ++ выгоду от неизменяемых строк?

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


Обновление:

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

Ответы [ 11 ]

44 голосов
/ 16 мая 2011

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

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

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

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

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

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

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

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

23 голосов
/ 27 мая 2010

Как мнение:

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

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

9 голосов
/ 05 мая 2011

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

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

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

  • Копирование не произошло
  • Если кто-то хочет скопировать, он может сделать это бесплатно
  • Техника применяется ко всем типам данных, а не только к строкам
3 голосов
/ 27 мая 2010

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

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

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

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

3 голосов
/ 27 мая 2010

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

2 голосов
/ 27 мая 2010
const std::string

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

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

1 голос
/ 15 февраля 2015

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

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

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

0 голосов
/ 31 мая 2012

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

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

0 голосов
/ 28 июня 2011

Строки изменчивы в Ruby.

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

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

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

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

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

Если вы не реализуете механизмы с интенсивным использованием процессора, я не понимаю, как.

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

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

0 голосов
/ 27 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...