Как реализован std::string?
Мне любопытно узнать, как реализован std::string и чем он отличается от строки c? Если в стандарте не указана какая-либо реализация, то любая реализация с объяснением была бы хороша тем, как она удовлетворяет строковому требованию, заданному стандартом?
5 ответов
Практически каждый использованный мной компилятор предоставляет исходный код для среды выполнения - так что, используете ли вы GCC, MSVC или что-то еще, у вас есть возможность взглянуть на реализацию. Тем не менее, большая часть или все std::string
будет реализован в виде шаблона кода, который может сделать для очень сложного чтения.
Книга Скотта Мейера "Эффективный STL" содержит главу о реализации std::string, которая представляет собой хороший обзор общих вариантов: "Пункт 15: Знайте об изменениях в string
Реализации".
Он говорит о 4 вариациях:
несколько вариантов реализации с подсчетом ссылок (обычно известной как копирование при записи) - когда строковый объект копируется без изменений, ссылка увеличивается, но фактические строковые данные - нет. Оба объекта указывают на одни и те же пересчитанные данные, пока один из объектов не изменит их, что приведет к "копированию при записи" данных. Варианты в том, где хранятся такие вещи, как refcount, блокировки и т. Д.
реализация "оптимизации коротких строк" (SSO). В этом варианте объект содержит обычный указатель на данные, длину, размер динамически выделяемого буфера и т. Д. Но если строка достаточно короткая, она будет использовать эту область для хранения строки вместо динамического выделения буфера.
Кроме того, в "Более исключительном C++" Херба Саттера есть приложение (Приложение A: "Оптимизации, которого нет (в многопоточном мире)"), в котором объясняется, почему в реализациях с перезаписанными копиями при записи часто возникают проблемы с производительностью в многопоточных приложениях из-за проблем синхронизации. Эта статья также доступна онлайн (но я не уверен, что она точно такая же, как в книге):
Обе эти главы стоит прочитать.
std::string - это класс, который обертывает некоторый внутренний буфер и предоставляет методы для управления этим буфером.
Строка в C это просто массив символов
Объяснение всех нюансов работы std::string здесь займет слишком много времени. Может быть, посмотрите на исходный код gcc http://gcc.gnu.org/ чтобы увидеть, как именно они это делают.
Пример реализации в ответе на этой странице.
Кроме того, вы можете посмотреть на реализацию gcc, если у вас установлен gcc. Если нет, вы можете получить доступ к их исходному коду через SVN. Большая часть std::string реализована с помощью basic_string, поэтому начните с нее.
Другим возможным источником информации является компилятор Watcom
Решение C++ для строк сильно отличается от c-версии. Первое и наиболее важное отличие заключается в том, что, когда c использует решение ASCIIZ, std::string и std::wstring используют два итератора (указателя) для хранения фактической строки. Основное использование строковых классов обеспечивает динамически распределенное решение, поэтому за счет затрат на ЦП и динамической обработки памяти это делает обработку строк более удобной.
Как вы, вероятно, уже знаете, C не содержит встроенного универсального строкового типа, а предоставляет только пару строковых операций через стандартную библиотеку. Одно из основных отличий между C и C++ в том, что C++ предоставляет упакованную функциональность, поэтому его можно рассматривать как фиктивный универсальный тип.
В C вам нужно пройти по строке, если вы хотите узнать ее длину, функция-член std::string::size() - это всего лишь одна инструкция (end - begin). Вы можете безопасно добавлять строки друг к другу, пока у вас есть память, поэтому вам не нужно беспокоиться об ошибках переполнения буфера (и, следовательно, об эксплойтах), потому что добавление создает больший буфер, если это необходимо.
Как кто-то говорил здесь ранее, строка получена из векторной функциональности, шаблонным способом, так что это облегчает работу с системами многобайтовых символов. Вы можете определить свой собственный строковый тип, используя typedef std::basic_string specific_str_t; выражение с любым произвольным типом данных в параметре шаблона.
Я думаю, что есть много плюсов и минусов с обеих сторон:
C++ string Плюсы: - Более быстрая итерация в определенных случаях (определенно используется размер, и не требуется данных из памяти, чтобы проверить, если вы находитесь в конце строки, сравнивая два указателя. Это может иметь значение с кэширование) - Операция буфера упакована со строковой функциональностью, поэтому меньше беспокоится о проблемах с буфером.
C++ string Минусы: - из-за динамического выделения памяти, основное использование может повлиять на производительность. (К счастью, вы можете указать строковому объекту, какой должен быть исходный размер буфера, поэтому, если вы не превысите его, он не будет выделять динамические блоки из памяти) - часто странные и противоречивые имена по сравнению с другими языками. это плохо в любом stl, но вы можете использовать его, и это вызывает немного специфическое чувство C++. - интенсивное использование шаблонов вынуждает стандартную библиотеку использовать решения на основе заголовков, поэтому это сильно влияет на время компиляции.
Это зависит от используемой вами стандартной библиотеки.
STLPort, например, является реализацией стандартной библиотеки C++, которая, помимо прочего, реализует строки.