C++中字符串可访问单个字符但整体打印为空的原因排查
反转字符串后打印为空,但单个字符可访问的原因及修复
你的问题核心出在空字符串的越界访问上,先看原代码里的关键问题:
#include <iostream> // using namespace std; std::string reverse_string(const std::string &str) { std::string reversed; // 这里创建的是空字符串,长度为0,内存仅包含终止符'\0' size_t size {str.length()}; for(int i{}; i < size/2; i++) { reversed[i] = str[(size-1)-i]; // 越界写入未分配的内存 reversed[(size-1)-i] = str[i]; // 同样属于越界操作 } return reversed; } int main() { std::string input = "Hello, World!"; std::string reversed = reverse_string(input); std::cout << reversed << std::endl; // 输出空 std::cout << reversed[0] << std::endl; // 能读出'!' return 0; }
为什么会出现矛盾现象?
std::string的operator[]不会自动扩容,空字符串的内部记录长度为0。你强行给reversed[i]赋值,本质是在写入字符串对象未分配的内存区域——这属于C++的未定义行为,运气好时进程不会崩溃,但内存操作完全不受字符串对象的管理。- 当用
cout打印整个字符串时,它会根据字符串内部记录的长度(此时还是0)输出,或者从起始地址读到第一个'\0',所以直接输出空。但单独访问reversed[0]时,是直接读取你越界写入的内存位置,刚好是之前赋值的'!',所以能打印出来。
修复方案
最直接的办法是先给reversed分配足够的内存,和原字符串长度一致:
std::string reverse_string(const std::string &str) { size_t size {str.length()}; std::string reversed(size, '\0'); // 初始化时指定长度,填充空字符 for(int i{}; i < size/2; i++) { reversed[i] = str[(size-1)-i]; reversed[(size-1)-i] = str[i]; } return reversed; }
也可以用resize方法扩容:
std::string reversed; reversed.resize(size); // 把字符串长度调整为原字符串的长度
更简洁的反转写法(新手参考)
如果不想手动写交换逻辑,也可以用标准库的std::reverse,或者从后往前逐个添加字符:
用标准库反转
#include <algorithm> // 需要包含这个头文件 std::string reverse_string(const std::string &str) { std::string reversed(str); std::reverse(reversed.begin(), reversed.end()); return reversed; }
手动遍历添加
std::string reverse_string(const std::string &str) { std::string reversed; reversed.reserve(str.size()); // 预分配内存,避免频繁扩容提升效率 for (int i = str.size() - 1; i >= 0; --i) { reversed.push_back(str[i]); } return reversed; }
内容的提问来源于stack exchange,提问作者Jerry
相关产品推荐
相关产品推荐

