一开始使用CArray<CStringArray, CStringArray&>& strsArr是错误的,核心问题在于CArray的模板参数使用了不可拷贝的CStringArray作为存储类型,且引用类型的第二个参数加剧了类型不兼容问题,这会直接触发编译错误。
1. 第一个核心错误:CArray的第一个模板参数(TYPE,存储类型)用了CStringArray
CArray是 MFC 的动态数组容器,其内部管理元素时需要执行拷贝、赋值、内存扩容时的元素移动等操作。但:
CStringArray是CArray<CString, CString&>的派生类,而 MFC 的CArray系列类的拷贝赋值运算符operator=被显式删除(这也是你之前遇到error C2280的原因)。- 当
CArray试图存储CStringArray对象时,内部的拷贝 / 赋值操作会触发 **error C2280: 尝试引用已删除的函数**,因为CStringArray不支持拷贝赋值,CArray无法完成元素的内存管理。
简单说:CStringArray是不可拷贝的类型,不能直接作为CArray的存储元素。
2. 第二个错误:第二个模板参数(ARG_TYPE,参数传递类型)用了CStringArray&(引用)
CArray的第二个模板参数ARG_TYPE的设计目的是简化函数参数传递(比如Add、GetAt等函数的参数类型),它的使用有个前提:必须和第一个参数TYPE兼容,且不能违背TYPE的特性。
- 即使忽略第一个错误,
CStringArray&作为ARG_TYPE也会导致CArray的成员函数(如Add)无法正常工作 —— 因为引用类型无法被CArray用于内部的元素拷贝,进一步加剧编译错误。 - 规范用法:如果
TYPE是普通可拷贝类型(如int、CString),ARG_TYPE可以用值类型或引用类型(如int/int&、CString/CString&);但如果TYPE是不可拷贝类型,这个参数的选择本身就没有意义。
正确的函数声明方案
解决思路是用指针替代CStringArray对象,因为指针是可拷贝的,且不会触发CStringArray的拷贝赋值操作。
CArray<CStringArray*, CStringArray*> &strsArr
CStringArray *icdStrArr = new CStringArray();
strsArr.Add(icdStrArr);
CArray<CStringArray*, CStringArray*>使用完后必须手动释放,因为这个容器存储的是CStringArray的堆指针(通过new创建的对象),容器本身只会管理指针的存储,不会自动释放指针指向的内存。
如果不手动释放,这些CStringArray对象会一直占用内存,直到程序结束,造成内存泄漏(尤其是频繁创建和使用这个容器时,泄漏会非常明显)。
正确的内存释放步骤
// 假设你有一个CArray<CStringArray*, CStringArray*>类型的对象cutedIcdArr
void ReleaseIcdArr(CArray<CStringArray*, CStringArray*>& cutedIcdArr)
{ // 第一步:遍历数组,释放每个CStringArray堆对象
for (int i = 0; i < cutedIcdArr.GetSize(); i++)
{
// 安全判断:避免空指针释放(虽然new一般不会返回nullptr,但建议加上)
if (cutedIcdArr[i] != nullptr)
{
delete cutedIcdArr[i]; // 释放CStringArray对象
cutedIcdArr[i] = nullptr; // 置空指针,避免野指针
}
}
// 第二步:清空数组中的指针(可选,但建议做,让数组变为空)
cutedIcdArr.RemoveAll();
}

955

被折叠的 条评论
为什么被折叠?



