C++定长字符串动态数组的实现问题与编译报错修复
编译报错根因
你遇到的编译错误核心原因是C++内置char数组类型不支持直接用赋值运算符做整体拷贝:
- 数组名是指向数组首元素的常量地址,本身是不可修改的左值,不能被赋值
- 编译器识别到你尝试把
const char[20]类型的字符串字面量直接赋值给char[20]类型的数组成员时,找不到匹配的类型转换和赋值逻辑,因此抛出类型不兼容的编译错误
原动态数组实现的现存问题
- 原实现的扩容拷贝逻辑本身可运行,但存在三法则违反风险:类自定义了析构函数释放动态内存,却没有显式定义拷贝构造和拷贝赋值逻辑,一旦发生AString对象的值拷贝,会出现同一块动态内存被多次释放的崩溃问题
- 你之前对动态数组赋值的认知存在偏差:POD结构体中的char数组成员,虽然可以通过结构体默认的赋值运算符完成逐成员拷贝,但单独的数组变量本身不支持直接用=赋值,所有针对数组内容的写入都需要逐元素拷贝完成
调整为直接管理定长char[20]动态数组的实现方案
调整后不再依赖_str结构体封装,直接管理连续的定长char数组块,核心改动如下:
- 类的私有成员调整为指向定长char数组的指针
char (*str)[20],替代原来的_str* str - Add方法的参数改为接收定长char数组的引用,避免数组退化为指针丢失长度信息
- 所有数组内容的写入使用安全的字符串拷贝接口完成,不使用直接赋值
完整的修正代码片段:
#include "stdafx.h" #include <iostream> #include <cstring> class AString { public: AString(); ~AString(); // 禁用默认拷贝,避免浅拷贝导致的二次释放问题 AString(const AString&) = delete; AString& operator=(const AString&) = delete; void Add(const char (&input)[20]); private: char (*str)[20]; // 指向长度为20的char数组的指针 int count; }; AString::AString() { std::cout << "Constructor" << std::endl; str = nullptr; count = 0; } AString::~AString() { std::cout << "Destructor" << std::endl; delete[] str; } void AString::Add(const char (&input)[20]) { // 申请扩容后的连续数组块 char (*new_block)[20] = new char[count + 1][20]; // 拷贝原有元素 for (int i = 0; i < count; i++) { strcpy_s(new_block[i], str[i]); } // 拷贝新增元素 strcpy_s(new_block[count], input); // 释放旧内存 delete[] str; str = new_block; count++; } int _tmain(int argc, _TCHAR* argv[]) { AString astring; char str1[20]; // 用安全拷贝接口给数组写入内容,不直接用=赋值 strcpy_s(str1, "0123456789012345678"); astring.Add(str1); std::cin.get(); return 0; }
关键注意事项
- 动态申请连续定长数组时,指针类型必须和数组元素类型匹配,不能用
char*替代指向定长数组的指针,否则会无法逐块访问每个独立的20字节字符串 - 所有针对char数组的内容写入,都需要用
strcpy_s、memcpy这类带长度校验的拷贝接口完成,不要用直接赋值的语法 - 手动管理动态内存的类,只要自定义了析构函数,就必须显式控制拷贝语义,从根源上避免浅拷贝的内存问题
内容的提问来源于stack exchange,提问作者user9543846
相关产品推荐
相关产品推荐

