MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Tipul std::string_view

Dacă parametrul are tipul std::string, atunci putem transmite atât un obiect de tip std::string, cât și un literal de șir. De exemplu:

#include <iostream>
  
void print(const std::string&);
int main()
{
    std::string message{"hello"};
    print(message);         // putem transmite un std::string
    print("Hello Work");    // putem transmite un literal de șir
}
 
void print(const std::string& text)
{
    std::cout << text << std::endl;
}

Aici șirul este transmis prin referință, ceea ce permite evitarea copierii inutile a caracterelor. Modificatorul const protejează șirul de modificări. Totuși, deși șirul este transmis prin referință, când parametrului îi transmitem un literal de șir, în memorie, în timpul conversiei literalului la tipul std::string, se face totuși copierea caracterelor și alocări suplimentare de memorie, ceea ce afectează negativ performanța.

Tipul std::string_view este conceput să rezolve această problemă. Este definit în modulul <string_view> și se comportă asemănător cu const std::string cu o excepție — string_view nu copiază caracterele obiectului șir indiferent dacă este std::string, literal de șir sau tablou de caractere. Prin urmare, ca tip de parametru este mai optim să folosim std::string_view decât referința constantă const std::string&. Și nu contează că parametrul poate fi transmis prin valoare, nu prin referință — copierea caracterelor tot nu va avea loc. În implementarea internă, std::string_view copiază doar lungimea șirului și un pointer la secvența de caractere.

Totuși, trebuie remarcat că lucrul cu tipul string_view presupune că caracterele șirului nu vor fi modificate, deoarece intern string_view reprezintă o constantă, indiferent dacă parametrului i se aplică modificatorul const.

Să modificăm programul de mai sus, folosind tipul std::string_view:

#include <iostream>
#include <string>
#include <string_view>
  
void print(std::string_view);
int main()
{
    std::string message{"hello"};
    print(message);         // putem transmite un std::string
    print("Hello Work");    // putem transmite un literal de șir
}
 
void print(std::string_view text)
{
    std::cout << text << std::endl;
}

În rest, tipul std::string_view implementează majoritatea funcțiilor similare cu cele ale tipului std::string. De exemplu, să găsim în șirul reprezentat de un string_view numărul de cuvinte:

#include <iostream>
#include <vector>
#include <string_view>
  
std::vector<std::string_view> get_words(std::string_view);
 
int main()
{
    std::string text = " An apple a day keeps the doctor away."; // Textul inițial
 
    std::vector<std::string_view> words = get_words(text);
 
    // afișăm numărul de cuvinte
    std::cout << "\nText contains " << words.size() << " words:" << std::endl;
    // afișăm toate cuvintele pe consolă
    for (const auto& word : words)
    {
        std::cout << word << std::endl;
    }
}
 
std::vector<std::string_view> get_words(std::string_view text)
{
    const std::string_view separators{ " ,;:.\"!?'*\n" };
    std::vector<std::string_view> words; // vector pentru stocarea cuvintelor
    size_t start { text.find_first_not_of(separators) }; // indexul primului caracter al primului cuvânt
    while (start != std::string_view::npos) // parcurgem șirul cât timp există caractere care nu sunt separatori
    {
        size_t end = text.find_first_of(separators, start + 1); // găsim sfârșitul cuvântului
        if (end == std::string_view::npos) // dacă nu găsim niciun separator
            end = text.length();        // setăm sfârșitul la lungimea textului
        words.push_back(text.substr(start, end - start)); // adăugăm cuvântul în vector
        start = text.find_first_not_of(separators, end + 1); // căutăm începutul următorului cuvânt
    }
    return words;
}

Practic, aici este implementat același program de numărare a cuvintelor ca și în articolul anterior, doar că textul este transmis ca un std::string_view. Pentru extragerea cuvintelor folosim funcții ale tipului string_view echivalente cu cele din std::string: find_first_not_of(), find_first_of(), length().

Trebuie menționat că pentru lucrul cu șiruri Unicode există și tipurile: std::wstring_view, std::u8string_view, std::u16string_view și std::u32string_view. Lucrul cu aceste tipuri este similar cu cel al std::string_view.