std::string_view
швидше в кількох випадках.
По-перше, std::string const&
вимагає, щоб дані знаходилися в a std::string
, а не в необробленому масиві C, char const*
повертається API API, 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&
є оптимальним за «a» std::string_view
. Якщо після виклику вам потрібно володіти копією рядка на невизначений термін, отримання побічної вартості є ефективним. Ви або будете знаходитись у корпусі SBO (і жодних виділень, лише декілька копій символів для його дублювання), або ви зможете перемістити виділений купою буфер в локальний std::string
. Маючи дві перевантаження std::string&&
і std::string_view
може бути швидше, але лише незначно, і це спричинить скромний розрив коду (що може коштувати вам усіх швидкостей).
¹ Невелика оптимізація буфера
² Фактичне використання.
std::string_view
- це лише абстракція пари (char * початок, char * end). Ви використовуєте його під час створенняstd::string
копії, це буде непотрібною копією.