#include <iostream>
#include <cstring>
using namespace std;
class mystring {
private:
char* buf; // 指向存储字符串的堆空间
int len; // 记录字符串长度
public:
// 可隐式调用的单参构造函数,使用列表初始化len
mystring(const char* s = "") : len(strlen(s)) {
buf = new char[len + 1];
strcpy(buf, s);
}
// 析构函数
~mystring() {
delete[] buf;
}
// 拷贝构造函数
mystring(const mystring& other) : len(other.len) {
buf = new char[len + 1];
strcpy(buf, other.buf);
}
// 赋值运算符重载
mystring& operator=(const mystring& other) {
if (this != &other) {
delete[] buf;
len = other.len;
buf = new char[len + 1];
strcpy(buf, other.buf);
}
return *this;
}
// 复制函数 - 接受mystring对象
void copy(const mystring& other) {
delete[] buf;
len = other.len;
buf = new char[len + 1];
strcpy(buf, other.buf);
}
// 复制函数 - 接受C风格字符串
void copy(const char* s) {
delete[] buf;
len = strlen(s);
buf = new char[len + 1];
strcpy(buf, s);
}
// 追加函数 - 接受mystring对象
void append(const mystring& other) {
char* temp = new char[len + other.len + 1];
strcpy(temp, buf);
strcat(temp, other.buf);
delete[] buf;
buf = temp;
len += other.len;
}
// 追加函数 - 接受C风格字符串
void append(const char* s) {
int slen = strlen(s);
char* temp = new char[len + slen + 1];
strcpy(temp, buf);
strcat(temp, s);
delete[] buf;
buf = temp;
len += slen;
}
// 比较函数 - 接受mystring对象
int compare(const mystring& other) const {
return strcmp(buf, other.buf);
}
// 比较函数 - 接受C风格字符串
int compare(const char* s) const {
return strcmp(buf, s);
}
// 显示字符串
void show() const {
cout << buf << endl;
}
// 返回指定位置的字符
char at(int pos) const {
if (pos >= 0 && pos < len) {
return buf[pos];
}
return '\0'; // 位置无效时返回空字符
}
};
int main() {
mystring str = "hello"; // 隐式调用单参构造函数
mystring ptr = "world"; // 使用列表初始化len
str.copy(ptr);
str.copy("你好");
str.append(ptr);
str.append("你好");
str.compare(ptr);
str.compare("你好");
str.show(); // 输出结果
cout << str.at(0) << endl; // 输出第0个字符
return 0;
}
以下是对 mystring 类实现的详细解析,按功能模块和关键设计点逐一说明:
1. 类的私有成员
cpp
运行
private:
char* buf; // 指向存储字符串的堆空间
int len; // 记录字符串长度设计目的:
使用动态内存分配(堆空间),避免固定大小数组的限制(如 char buf[256])。
len 存储字符串实际长度,避免重复调用 strlen() 提高效率。
2. 构造函数
cpp
运行
mystring(const char* s = "") : len(strlen(s)) {
buf = new char[len + 1];
strcpy(buf, s);
}关键点:
单参构造函数:参数为 const char*,支持隐式类型转换(如 mystring str = "hello";)。
列表初始化:len(strlen(s)) 在对象构造前初始化 len,比在函数体中赋值更高效。
内存分配:new char[len + 1] 分配足够空间(含字符串结束符 '\0')。
字符串复制:strcpy 将输入字符串复制到堆空间。
3. 析构函数
cpp
运行
~mystring() {
delete[] buf;
}内存管理:释放 buf 指向的堆空间,防止内存泄漏。
若不定义析构函数,对象销毁时 buf 的内存不会自动释放。
4. 拷贝构造函数
cpp
运行
mystring(const mystring& other) : len(other.len) {
buf = new char[len + 1];
strcpy(buf, other.buf);
}深拷贝:
分配新的内存空间,复制原对象的字符串内容。
避免浅拷贝(直接复制指针)导致多个对象共享同一块内存,析构时重复释放。
5. 赋值运算符重载
cpp
运行
mystring& operator=(const mystring& other) {
if (this != &other) {
delete[] buf;
len = other.len;
buf = new char[len + 1];
strcpy(buf, other.buf);
}
return *this;
}自我赋值检查:if (this != &other) 避免自我赋值时释放内存后再复制。
步骤:
释放当前对象的内存。
分配新内存并复制字符串内容(深拷贝)。
返回引用:支持链式赋值(如 a = b = c)。
6. 复制函数(copy)
cpp
运行
void copy(const mystring& other) { ... }
void copy(const char* s) { ... }重载实现:
接受 mystring 对象:复制其 len 和 buf 内容。
接受 const char*:计算长度并复制字符串。
内存管理:
先释放当前 buf 的内存,再分配新内存,防止内存泄漏。
7. 追加函数(append)
cpp
运行
void append(const mystring& other) { ... }
void append(const char* s) { ... }步骤:
计算新长度 len + other.len(或 len + strlen(s))。
分配临时空间 temp,复制原字符串和追加内容。
释放原 buf,将 temp 赋值给 buf。
动态扩展:避免固定大小数组的限制,但需注意频繁追加可能导致性能开销。
8. 比较函数(compare)
cpp
运行
int compare(const mystring& other) const { ... }
int compare(const char* s) const { ... }使用 strcmp:
返回值:
< 0:当前字符串小于参数。
0:字符串相等。
> 0:当前字符串大于参数。
const 修饰:标记为常量成员函数,不修改对象状态。
9. 显示函数(show)
cpp
运行
void show() const {
cout << buf << endl;
}输出字符串:直接打印 buf,利用 cout 对 char* 的重载。
const 修饰:不修改对象状态。
10. 字符访问函数(at)
cpp
运行
char at(int pos) const {
if (pos >= 0 && pos < len) {
return buf[pos];
}
return '\0'; // 位置无效时返回空字符
}边界检查:确保访问位置合法,避免越界。
安全性:返回 '\0'(而非未定义行为),增强程序健壮性。
11. 主函数测试
cpp
运行
int main() {
mystring str = "hello"; // 隐式构造
mystring ptr = "world";
str.copy(ptr); // 复制 "world"
str.copy("你好"); // 复制 "你好"
str.append(ptr); // 追加 "world"
str.append("你好"); // 追加 "你好"
str.compare(ptr); // 比较
str.compare("你好"); // 比较
str.show(); // 输出:你好world你好
cout << str.at(0) << endl; // 输出:你
}功能验证:依次测试构造、复制、追加、比较、显示和字符访问。
总结
该实现通过动态内存管理和深拷贝机制,解决了固定大小数组的限制和浅拷贝导致的内存问题。每个成员函数都遵循以下原则:内存安全:避免泄漏和野指针。
功能完整:提供字符串操作的核心功能。
异常安全:边界检查和状态维护。
性能优化:减少不必要的内存操作和字符串长度计算。通过这些设计,mystring 类实现了一个简单但功能完整的字符串管理系统。
简化易理解版本代码
#include <iostream>
#include <cstring>
using namespace std;
class mystring {
private:
char* buf;
int len;
public:
mystring() {}
mystring(const char* r);
void copy(mystring r);
bool compare(mystring r);
void append(mystring r);
char at(int index);
void show();
};
mystring::mystring(const char* r)
: len(strlen(r)), buf((char*)calloc(1, len + 1)) {
strncpy(buf, r, len);
}
void mystring::copy(mystring r) {
if (len < r.len) {
len = r.len;
free(buf);
buf = (char*)calloc(1, len + 1);
}
strncpy(buf, r.buf, len);
}
bool mystring::compare(mystring r) {
return strcmp(buf, r.buf) == 0;
}
void mystring::append(mystring r) {
len = len + r.len;
char* temp = buf;
buf = (char*)calloc(1, len + 1);
strcpy(buf, temp);
strcat(buf, r.buf);
}
char mystring::at(int index) {
return buf[index];
}
void mystring::show() {
cout << buf << endl;
}
int main(int argc, const char** argv) {
mystring str = "hello";
mystring ptr = "world";
str.show();
ptr.show();
str.copy(ptr);
str.show();
str.copy("aefserfsrfgresfg");
str.show();
cout << (str.compare(ptr)) << endl;
cout << (str.compare("world")) << endl;
str.append(ptr);
str.show();
str.append("world");
str.show();
cout << str.at(10) << endl;
return 0;
}