std::string_view
быстрее в нескольких случаях.
Во-первых, std::string const&
требуется , чтобы данные находились в std::string
массиве C, а не в необработанном массиве C, char const*
возвращались API C, std::vector<char>
производились каким-либо механизмом десериализации и т. Д. Преобразование избегаемого формата позволяет избежать копирования байтов и (если строка длиннее, чем SBO¹ для конкретной std::string
реализации) избегает выделения памяти.
void foo( std::string_view bob ) {
std::cout << bob << "\n";
}
int main(int argc, char const*const* argv) {
foo( "This is a string long enough to avoid the std::string SBO" );
if (argc > 1)
foo( argv[1] );
}
Распределения в этом string_view
случае не выполняются , но было бы, если бы foo
взяли std::string const&
вместо string_view
.
Вторая действительно важная причина заключается в том, что она позволяет работать с подстроками без копирования. Предположим, вы анализируете 2-гигабайтную строку json (!) ². Если вы анализируете его std::string
, каждый такой узел синтаксического анализа, где хранятся имя или значение узла, копирует исходные данные из строки размером 2 ГБ в локальный узел.
Вместо этого, если вы анализируете его в std::string_view
s, узлы ссылаются на исходные данные. Это может сэкономить миллионы выделений и сократить вдвое требования к памяти при разборе.
Ускорение, которое вы можете получить, просто смешно.
Это крайний случай, но другие случаи «получить подстроку и работать с ней» также могут привести к приличному ускорению string_view
.
Важной частью решения является то, что вы теряете при использовании std::string_view
. Это не так много, но это что-то.
Вы теряете неявное нулевое завершение, и это все. Таким образом, если одна и та же строка будет передана 3 функциям, каждая из которых требует нулевого терминатора, std::string
может быть целесообразно преобразовать в один раз. Таким образом, если известно, что вашему коду нужен нулевой терминатор, и вы не ожидаете, что строки будут передаваться из буферов в стиле C или тому подобное, возможно, возьмите a std::string const&
. В противном случае возьмите std::string_view
.
Если std::string_view
бы был флаг, который указывал, что он был завершен нулем (или что-то более причудливое), он удалил бы даже эту последнюю причину использовать std::string const&
.
Есть случай, когда взятие std::string
без не const&
является оптимальным по сравнению с std::string_view
. Если вам нужно владеть копией строки на неопределенный срок после вызова, эффективный захват по значению. Вы будете либо в случае SBO (и без выделения, всего несколько копий символов для его дублирования), либо вы сможете переместить выделенный в куче буфер в локальный std::string
. Имея две перегрузки std::string&&
и std::string_view
может быть быстрее, но лишь незначительно, и это вызвало бы скромное разрастание кода (который может стоить вам все преимущества скорости).
¹ Оптимизация малого буфера
² Фактический вариант использования.
std::string_view
это просто абстракция пары (char * begin, char * end). Вы используете его при созданииstd::string
ненужной копии.