Как я могу заменить член std::string на строку ограниченного размера без кучи?
У меня есть кодовая база с повсеместной структурой данных; и указанная структура имеет член std :: string. Теперь по причинам я хочу, чтобы эта кодовая база работала, когда std :: string недоступен, и фактически без динамического выделения памяти (по крайней мере, не обычным способом). Я также могу проверить, что этот строковый член никогда не имеет строки длиннее M символов (а M мало).
Теперь, чем мне заменить std :: string, чтобы мне не пришлось много переписывать, с одной стороны; и что мои ограничения удовлетворены другим?
Примечание:
- Я не могу переместить вычисление строки во время компиляции.
- Ничего страшного, если в решении есть только тривиальный конструктор,
const char*
конструктор или и то, и другое. - Решения с использованием
std::string_view
может быть актуальным (но я не уверен, будет ли это полезно).
2 ответа
вероятно, будет достойным и простым вариантом для исследования. Объем перезаписи может быть больше или меньше в зависимости от того, как вы использовали строковый член до сих пор.
Если "std ::stringiness" члена используется часто, то вы могли бы уменьшить количество перезаписи, реализовав собственный класс, который предлагает аналогичный интерфейс, но внутренне использует
char[M + 1]
.
boost::static_string
упомянутый Дрю Дорманн является шаблоном для такого класса.
PS Если вы все еще можете использовать динамическую память и ограничены в ее использовании, то вы потенциально можете продолжать использовать
std::string
вместо этого с настраиваемым распределителем, как упоминал Галик .
Потенциальное решение с минимальными хлопотами могло бы использовать особенности вашего случая, жертвуя общностью ради простоты:
Вы написали, что строка, которую хотите заменить, на самом деле является членом другой структуры. Это уже позволяет использовать член массива структуры, как предлагает @eerorika, не беспокоясь о распаде массива. Но - массивы не являются интерфейсом std :: string.
Вы сказали, что не видели, как
std::string_view
было бы полезно - и это потому, что для него нет места для хранения.
Что ж, объедините два! ... нет, не пишите новый класс с хранилищем и строковым интерфейсом. Скорее добавьте
char [M+1]
field в вашу структуру с новым именем поля и используйте исходное имя поля для string_view, смотрящего на массив (с соответствующей длиной, конечно)!
Это немного усложняет конструирование и присваивание - то есть это больше не тривиальная поэлементная конструкция - но тогда вы сможете передавать этот объект и использовать то же поле, что и раньше, например std ::string.
struct ubiquitous {
// other members
char[M+1] string_data;
std::string_view original_field;
// apply rule of 5: ctor, move ctor, assignment, move assignment
// and a trivial dtor (at least for your two fields)
// ... so, a "rule of 4" in this case
};
Если у вас нет
string_view
доступный, то есть это код до C++17, тогда вы можете получить перенесенный обратно string_view Мартина Моэна (GitHub).