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



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




  • тривиально потокобезопасным

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

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

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


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



выиграет ли C++ от неизменяемых строк?



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





обновление:



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

657   11  

11 ответов:

Как мнение:

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

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

я обнаружил, что большинство людей в этой теме действительно не понимают, что 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. Это должно быть то, о чем я говорю.

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

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

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

  • никакой копии не было
  • если кто-то хочет скопировать он свободен сделать это
  • методика применяется ко всем типам данных, а не только строки

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

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

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

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

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

const std::string

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Comments

    Ничего не найдено.