C++自定义MyString类重载>>运算符动态读取cin输入且不依赖std::string
问题根因
- 运算符参数错误:重载
operator>>需要修改传入的MyString实例,你给参数加了const修饰,属于逻辑错误,且str成员是私有属性,const实例无法修改。 - 缓冲区未初始化/空间不足:直接调用
is >> other.str时,要求str指向一块预先分配的、足够容纳输入内容的内存空间。你的str大概率是未初始化的野指针,或者分配的空间远小于输入的字符串长度,写入越界直接触发堆损坏。
不依赖std::string的实现方案
核心思路是逐个读取输入流的字符,动态扩容内部缓冲区,完全自主管理内存,实现代码如下:
#include <iostream> // 如果不想引入cctype,可以自行实现空白符判断逻辑,替换下方的std::isspace调用即可 #include <cctype> class MyString { private: char* str = nullptr; size_t length = 0; size_t capacity = 0; // 记录缓冲区实际可用大小 // 内部扩容函数 void reserve(size_t new_cap) { if (new_cap <= capacity) return; char* new_buf = new char[new_cap]; // 拷贝原有内容 for (size_t i = 0; i < length; i++) { new_buf[i] = str[i]; } // 释放旧内存 delete[] str; str = new_buf; capacity = new_cap; } public: // 默认构造 MyString() = default; // 析构函数,必须实现避免内存泄漏 ~MyString() { delete[] str; } // 可选:获取C风格字符串接口 const char* c_str() const { return str ? str : ""; } size_t size() const { return length; } friend std::istream& operator>>(std::istream& is, MyString& other) { // 先清空原有内容 other.length = 0; // 初始分配16字节缓冲区,可按需调整初始大小 if (other.capacity < 16) { other.reserve(16); } char ch; // 跳过开头的空白符,和标准cin>>行为对齐 while (is.get(ch) && std::isspace(static_cast<unsigned char>(ch))) {} // 读取内容直到遇到空白符或流结束 while (is && !std::isspace(static_cast<unsigned char>(ch))) { // 空间不足时扩容为原来的2倍 if (other.length + 1 >= other.capacity) { other.reserve(other.capacity * 2); } other.str[other.length++] = ch; is.get(ch); } // 补字符串结束符 if (other.str) { other.str[other.length] = '\0'; } // 如果是因为遇到空白符停止,把空白符放回输入流 if (is) { is.unget(); } return is; } };
注意事项
- 你需要自行实现拷贝构造函数、拷贝赋值运算符、移动构造、移动赋值函数,避免浅拷贝导致的double free、内存泄漏问题,符合C++三五法则要求。
- 如果需要支持读取包含空格的整行内容,可以修改判断逻辑,把停止条件从遇到空白符改为遇到换行符即可,和
std::getline行为对齐。
内容的提问来源于stack exchange,提问作者Alex Cai
相关产品推荐
相关产品推荐

