Sobes.tech
Middle

Kokie yra būdai optimizuoti darbą su eilutėmis C++?

sobes.tech AI

Atsakymas iš AI

  1. Naudokite std::string_view perduotiems eilutėms be duomenų kopijavimo.
  2. Taikykite <string> ir <algorithm> bibliotekų algoritmus (find, search) vietoje rankinio iteravimo.
  3. Iš anksto rezervuokite atmintį naudodami reserve, kad sumažintumėte peradresavimų skaičių didinant eilutę.
  4. Naudokite mažo dydžio eilutės buferį (Small String Optimization - SSO) std::string (jei tai įgyvendina kompiliatorius).
  5. Jei reikia greitos didelio kiekio eilutės sujungimo, naudokite std::stringstream arba pridėkite elementus po vieną į vieną rezultatą, iš anksto rezervuodami vietą.
  6. Naudokite specialias bibliotekas, optimizuotas darbui su eilutėmis, skirtas konkrečioms užduotims (pavyzdžiui, reguliarios išraiškos).
  7. Laikykite eilutes statinėje atmintyje arba pulte, kad išvengtumėte dinaminio paskirstymo dirbant su nuolatinėmis eilutėmis.
  8. Naudokite žemo lygio C funkcijas (memcpy, memmove) didelių duomenų kopijavimui, jei tai saugu ir pagrįsta.

Pavyzdys naudojant std::string_view:

#include <string>
#include <string_view>
#include <iostream>

void print_string(std::string_view sv) {
    std::cout << sv << std::endl;
}

int main() {
    std::string s = "Hello, world!";
    print_string(s); // Be kopijavimo

    const char* c_str = "Dar vienas eilutė";
    print_string(c_str); // Taip pat be kopijavimo

    return 0;
}

Pavyzdys naudojant reserve:

#include <string>
#include <iostream>

int main() {
    std::string s;
    s.reserve(100); // Iš anksto rezervuokite vietą
    for (int i = 0; i < 100; ++i) {
        s += 'a'; // Pridėkite simbolius, mažiau peradresavimų
    }
    std::cout << "Dydis: " << s.size() << ", Talpa: " << s.capacity() << std::endl;
    return 0;
}

Lyginant sujungimą:

#include <string>
#include <sstream>
#include <iostream>
#include <chrono>

int main() {
    const int count = 1000;
    std::string chunk = "abc";

    // Sujungimas naudojant `+=` operatorių
    auto start1 = std::chrono::high_resolution_clock::now();
    std::string result1;
    result1.reserve(count * chunk.size()); // Optimizacija su rezervavimu
    for (int i = 0; i < count; ++i) {
        result1 += chunk;
    }
    auto end1 = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed1 = end1 - start1;
    std::cout << "Operator += (su rezervu): " << elapsed1.count() << " s" << std::endl;

    // Naudojant `stringstream`
    auto start2 = std::chrono::high_resolution_clock::now();
    std::stringstream ss;
    for (int i = 0; i < count; ++i) {
        ss << chunk;
    }
    std::string result2 = ss.str();
    auto end2 = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed2 = end2 - start2;
    std::cout << "stringstream: " << elapsed2.count() << " s" << std::endl;

    return 0;
}

(Pastaba: šių metodų našumas gali skirtis priklausomai nuo kompiliatoriaus ir standartinės bibliotekos).