最高效安全的方式是用 std::string 构造函数:单字符重复用 std::string(count, ch);多字符重复需先 reserve(size*repeat) 再循环 append,避免 O(n²) 重分配。
std::string 构造函数直接初始化重复字符串最高效、最安全的方式不是拼接,而是让 std::string 自己构造:它有一个接受 count 和 char 的构造函数,适用于单字符重复;若要重复整个字符串(如 "abc" 重复 3 次得 "abcabcabc"),则需手动计算长度并预分配内存。
常见错误是用 += 循环拼接——每次扩容可能触发多次内存重分配,时间复杂度接近 O(n²)。
'x'):std::string s(1000, 'x');
"ab" 重复 5 次):std::string pattern = "ab";
int repeat = 5;
std::string result;
result.reserve(pattern.size() * repeat); // 关键:避免反复 realloc
for (int i = 0; i < repeat; ++i) {
result += pattern;
}std::string result;
for (int i = 0; i < repeat; ++i) {
result += pattern; // 每次 += 可能触发 copy + resize
}std::string::append 替代 += 提升可读性与控制力append 和 += 在功能上等价,但 append 提供更明确的重载,比如按子串范围追加,也更容易配合 reserve 形成清晰意图。编译器优化后性能几乎无差别,但代码更易维护。
append:result.append(pattern); // 等价于 result += pattern
"hello world" 的前 3 字符重复 4 次):std::string s = "hello world"; s.append(s.substr(0, 3), 4); // 注意:substr 返回新 string,这里会复制;更高效应直接循环 append(s, 0, 3)
for (int i = 0; i < 4; ++i) {
result.append(s, 0, 3); // 直接从 s 的 [0,3) 区间 append,不生成临时 substr
}C++17 起,std::string 的移动语义更激进,但某些写法仍会意外创建临时对象。例如 result += pattern + "x" 中,pattern + "x" 先构造临时 std::string,再 move 进 result——这比直接 result += pattern; result += 'x'; 多一次分配。
result += pattern + "_suffix"; // 生成中间 string
result.append(pattern);
result.append("_suffix");append(const char*, size_t) 避免 strlen:result.append("_suffix", 7);
std::string_view 延迟拼接
如果重复字符串只是用于输出或传给某个 API,且生命周期短,没必要立即构造完整副本。用 std::string_view 表示“逻辑上的重复”,配合自定义输出函数,可彻底避免内存分配。
但注意:std::string_view 不拥有数据,不能返回局部变量的 view;也不能直接用于需要 const char* 的旧接口(除非调用 .data() 且确保源字符串生命周期足够长)。
void write_repeated(std::ostream& os, std::string_view pat, int n) {
for (int i = 0; i < n; ++i) {
os << pat;
}
}
// 调用:write_repeated(std::cout, "abc", 1000); // 零分配char buf[4096];
int len = snprintf(buf, sizeof(buf), "%.*s%.*s%.*s",
3, "abc", 3, "abc", 3, "abc"); // 手动展开,仅适合 repeat 数极小重复字符串看似简单,但实际容易在 reserve 忘记、临时对象滥用、以及误用 substr 上栽跟头。最稳的路径是:先 reserve,再循环 append,永远优先考虑构造而非拼接。