Quindi stavo giocando con del codice e volevo vedere quale metodo di conversione di uno std :: string in maiuscolo fosse più efficiente. Ho pensato che i due sarebbero stati in qualche modo simili per quanto riguarda le prestazioni, ma ero terribilmente in errore. Ora mi piacerebbe scoprire perché.Conversione da std :: string in maiuscolo: maggiore differenza di prestazioni?
Il primo metodo di conversione della stringa funziona come segue: per ogni carattere nella stringa (salva la lunghezza, itera da 0 alla lunghezza), se è tra 'a' e 'z', quindi spostalo in modo che sia invece tra 'A' e 'Z'.
Il secondo metodo funziona come segue: per ogni carattere nella stringa (a partire da 0, continuare fino a quando non si preme un terminatore null), applicare la funzione build toupper().
Ecco il codice:
#include <iostream>
#include <string>
inline std::string ToUpper_Reg(std::string str)
{
for (int pos = 0, sz = str.length(); pos < sz; ++pos)
{
if (str[pos] >= 'a' && str[pos] <= 'z') { str[pos] += ('A' - 'a'); }
}
return str;
}
inline std::string ToUpper_Alt(std::string str)
{
for (int pos = 0; str[pos] != '\0'; ++pos) { str[pos] = toupper(str[pos]); }
return str;
}
int main()
{
std::string test = " abcdefghijklmnopqrstuvwxyzABCDEFG[email protected]#$%^&*()_+=-`'{}[]\\|\";:<>,./?";
for (size_t i = 0; i < 100000000; ++i) { ToUpper_Reg(test); /* ToUpper_Alt(test); */ }
return 0;
}
Il primo metodo ToUpper_Reg
voluti circa 169 secondi per 100 milioni di iterazioni.
Il secondo metodo Toupper_Alt
ha richiesto circa 379 secondi per 100 milioni di iterazioni.
Cosa dà?
Edit: ho cambiato il secondo metodo in modo che itera la stringa come il primo non (impostare la lunghezza da parte, ciclo while meno di lunghezza) ed è un po 'più veloce, ma ancora circa il doppio lento.
Edit 2: Grazie a tutti per i vostri contributi! I dati su cui lo userò sono garantiti per essere ascii, quindi penso che per il momento rimarrò con il primo metodo. Tengo a mente che toupper
è specifico per le impostazioni locali quando/se necessario.
toupper è più lento di quello che si fa in _Reg perché fa più di quello che si fa in Reg? – Almo
Perché non aggiungete anche la trasformazione standard in C++, 'std :: transform (s.begin(), s.end(), s.begin(), (int (*) (int)) std :: toupper); '? (È necessario '#include', '' e ''.) –
Wow, questo è un boccone. Per curiosità, cosa c'è nella parte '(int (*) (int))'? –