Я использую внутреннюю библиотеку, которая была разработана для имитации предложенной библиотеки C ++ , и иногда в последние несколько лет я вижу, что ее интерфейс изменился с использования std::string
на string_view
.
Поэтому я покорно изменяю свой код, чтобы соответствовать новому интерфейсу. К сожалению, я должен передать параметр std :: string и возвращаемое значение std :: string. Итак, мой код изменился примерно так:
void one_time_setup(const std::string & p1, int p2) {
api_class api;
api.setup (p1, special_number_to_string(p2));
}
в
void one_time_setup(const std::string & p1, int p2) {
api_class api;
const std::string p2_storage(special_number_to_string(p2));
api.setup (string_view(&p1[0], p1.size()), string_view(&p2_storage[0], p2_storage.size()));
}
Я действительно не вижу, что это изменение купило мне как клиенту API, кроме большего количества кода (возможно, облажаться). Вызов API менее безопасен (из-за того, что API больше не владеет хранилищем своих параметров), вероятно, сохранил мою программу 0 (из-за того, что компиляторы оптимизации теперь могут это сделать), и даже если бы она сохраняла работу, это было бы только пара распределений, которые не будут и никогда не будут выполнены после запуска или где-то в большом цикле. Не для этого API.
Однако, этот подход, кажется, следует совету, который я вижу в другом месте, например, этот ответ :
Кроме того, начиная с C ++ 17, вы должны избегать передачи const std :: string & в пользу std :: string_view:
Я нахожу этот совет удивительным, так как кажется, что он выступает за повсеместную замену относительно безопасного объекта на менее безопасный объект (в основном прославленный указатель и длину), главным образом для целей оптимизации.
Так когда же следует использовать string_view, а когда нет?
источник
std::string_view
конструктор напрямую, вы должны просто передать строки в метод, принимаяstd::string_view
непосредственно, и он будет автоматически преобразован.<string>
шапке и происходит автоматически. Этот код обманчив и неправильн.Ответы:
std::string
(non-const, non-ref). Эта опция дает вам возможность явно перемещать значение, если вы знаете, что оно никогда больше не будет использоваться в контексте вызова.std::string_view
(const, non-ref), это потому, чтоstring_view
можно обрабатыватьstd::string
иchar*
легко без проблем и без копирования. Это должно заменить всеconst std::string&
параметры.В конечном итоге вам никогда не нужно вызывать
std::string_view
конструктор, как вы.std::string
имеет оператор преобразования, который обрабатывает преобразование автоматически.источник
std::string_view
проще в использовании. Если разработчик использует его не по назначению, это ошибка программирования.std::string_view
строго не владеющий.const, non-ref
? Параметр const соответствует конкретному использованию, но в общем случае считается неконстантным. А ты пропустил 3. Можно принимать ломтикиconst std::string_view &
вместоconst std::string &
?A
std::string_view
приносит некоторые преимущества aconst char*
для C ++: в отличие отstd::string
string_viewstd::string&
.Это означает, что string_view может часто избегать копий, не имея дело с необработанными указателями.
В современном коде
std::string_view
следует заменить практически все виды использованияconst std::string&
параметров функции. Это должно быть совместимым с исходным кодом изменением, посколькуstd::string
объявляет оператор преобразования вstd::string_view
.То, что представление строки не помогает в вашем конкретном случае использования, когда вам все равно нужно создавать строку, не означает, что это плохая идея в целом. Стандартная библиотека C ++ имеет тенденцию быть оптимизированной для универсальности, а не для удобства. «Менее безопасный» аргумент не выполняется, так как нет необходимости создавать строковое представление самостоятельно.
источник
std::string_view
является отсутствиеc_str()
метода, что приводит к ненужным промежуточнымstd::string
объектам, которые необходимо создавать и размещать. Это особенно проблема в низкоуровневых API.abcdef\0
и строковое представление, указывающее наcde
подстроку, после нулевойe
строки после - нет исходной строкиf
. В стандартных также отмечает: «данные () может возвращать указатель на буфер , который не является нулем. Поэтому, как правило, ошибочно передавать data () в функцию, которая принимает только const charT * и ожидает строку с нулевым символом в конце ».Я думаю, что это немного неправильное понимание цели этого. Хотя это и есть «оптимизация», вы должны думать об этом как о том, чтобы избавиться от необходимости использовать a
std::string
.Пользователи C ++ создали десятки различных классов строк. Строковые классы фиксированной длины, SSO-оптимизированные классы с размером буфера в качестве параметра шаблона, строковые классы, в которых хранится хеш-значение, используемое для их сравнения, и т. Д. Некоторые люди даже используют строки на основе COW. Если есть что-то, что любят программисты на C ++, это пишут строковые классы.
И это игнорирует строки, которые создаются и принадлежат библиотекам C. Голый
char*
с, может быть, с размером какой-то.Поэтому, если вы пишете какую-то библиотеку и берете a
const std::string&
, пользователь теперь должен взять любую строку, которую он использовал, и скопировать ее в astd::string
. Может быть, десятки раз.Если вы хотите получить доступ к
std::string
специфическому для строки интерфейсу, зачем вам копировать строку? Это такая трата.Принципиальные причины не принимать
string_view
в качестве параметра:Если ваша конечная цель - передать строку в интерфейс, который принимает строку, оканчивающуюся NUL (
fopen
и т. Д.).std::string
гарантированно прекращается NUL;string_view
нет. И очень просто вставить представление, чтобы оно не заканчивалось NUL; Подстрока astd::string
копирует подстроку в NUL-концевой диапазон.Я написал специальный тип стиля string_view с завершением NUL для именно этого сценария. Вы можете выполнять большинство операций, но не те, которые нарушают его NUL-завершенное состояние (обрезка с конца, например).
Жизненные проблемы. Если вам действительно нужно скопировать это
std::string
или иным образом получить массив символов, чтобы пережить вызов функции, лучше указать это заранее, взяв aconst std::string &
. Или простоstd::string
в качестве параметра значения. Таким образом, если у них уже есть такая строка, вы можете немедленно требовать владения ею, и вызывающая сторона может перейти в строку, если им не нужно хранить ее копию.источник
string_view
это тип lingua franca, который может работать с чем угодно.string_view
этим легко.