C++中如何使用new将类的字符串成员变量分配到堆内存
C++ 类内动态分配字符串内存的实现方案
原有代码的错误点
- 内存分配长度不足:C 风格字符串以
\0作为结束标志,std::string::length()返回的是有效字符长度,不包含结束符,你当前分配的空间少了1字节,会导致strcpy越界写入,触发未定义行为 - 函数参数不匹配:
strcpy要求第二个入参为const char*类型,直接传入std::string对象无法编译,需要调用c_str()方法获取对应的C风格字符串指针 - 缺失资源管理相关函数:手动分配堆内存后必须配套实现析构函数释放内存,同时按照C++三五规则,还需要补充拷贝构造函数、拷贝赋值运算符重载,避免浅拷贝导致的重复释放问题
修正后的完整实现代码
#include <iostream> #include <cstring> #include <string> class Studi { private: unsigned int matNr; char* name; public: // 修正后的构造函数 Studi(const std::string& k_name, unsigned int k_matNr) { // 多分配1字节存储结束符\0 name = new char[k_name.length() + 1]; // 调用c_str()获取C风格字符串指针 strcpy(name, k_name.c_str()); matNr = k_matNr; } // 析构函数:释放name指向的堆内存,避免内存泄漏 ~Studi() { delete[] name; } // 拷贝构造函数:实现深拷贝,避免两个对象指向同一块内存 Studi(const Studi& other) { matNr = other.matNr; name = new char[strlen(other.name) + 1]; strcpy(name, other.name); } // 拷贝赋值运算符重载:同样实现深拷贝,处理自赋值场景 Studi& operator=(const Studi& other) { if (this == &other) return *this; // 先释放当前对象的原有内存 delete[] name; // 深拷贝新对象的内容 matNr = other.matNr; name = new char[strlen(other.name) + 1]; strcpy(name, other.name); return *this; } // 测试用的成员函数,打印对象信息 void printInfo() const { std::cout << "姓名:" << name << ",学号:" << matNr << std::endl; } }; // 简单测试逻辑 int main() { Studi s1("张三", 2023001); s1.printInfo(); Studi s2 = s1; // 调用拷贝构造 s2.printInfo(); Studi s3("李四", 2023002); s3 = s1; // 调用拷贝赋值 s3.printInfo(); return 0; }
析构函数必要性说明
如果不实现析构函数,Studi对象销毁时只会回收栈上存储的matNr和name指针本身的内存,name指向的堆上的字符串内存不会被自动回收,会造成内存泄漏;如果发生对象拷贝,默认的浅拷贝逻辑会让多个对象的name指针指向同一块堆内存,第一个对象销毁时会释放该内存,后续其他对象销毁时会尝试重复释放同一块内存,直接导致程序崩溃。
内容的提问来源于stack exchange,提问作者Tonda
相关产品推荐
相关产品推荐

