@Daniel a fourni une implémentation qui est significativement plus rapide que les autres réponses dans sa branche d'exécution primaire (où n > 1 et str n'est pas vide). Cependant, les cas limites sont traités de manière beaucoup plus inefficace qu'ils ne pourraient l'être.
Cette mise en œuvre corrige ces problèmes :
#include <string>
#include <cstddef>
std::string repeat(size_t n, const std::string& str) {
if (n == 0 || str.empty()) return {};
if (n == 1) return str;
const auto period = str.size();
if (period == 1) return std::string(n, str.front());
std::string ret(str);
ret.reserve(period * n);
std::size_t m {2};
for (; m < n; m *= 2) ret += ret;
ret.append(ret.c_str(), (n - (m / 2)) * period);
return ret;
}
Une comparaison des deux implémentations sur quick-bench.com montre les différences suivantes dans ces cas particuliers. Clang 13.0 est le premier chiffre et GCC 10.3 le second. Optimisation -O3 dans tous les cas.
- Pour n == 0, cette implémentation est (9x / 11x) plus rapide.
- Pour str.empty() == true, il est (2,4x / 3,4x) plus rapide.
- Pour n == 1 et str.size() > 1, il est (2.1x / 1.4x) plus rapide.
- Et pour str.size() == 1, il est (1,3x / 1,2x) plus rapide.
Le problème avec l'implémentation originale se résume à passer str
dans la fonction par valeur. Ceci invoque une copie de str
à chaque appel à repeat
qui est inutile dans certains cas particuliers, notamment lorsque n == 0.