VS2019 C++报错C2280:尝试引用CBrush已删除函数如何排查
问题根因
C2280报错的本质是你调用了被显式删除的拷贝构造函数。你使用的CBrush是MFC的GDI对象类,这类资源持有类的拷贝构造、拷贝赋值运算符默认被MFC框架删除——因为GDI对象是Windows内核资源,随意拷贝会导致资源泄漏、重复释放等问题。
你写的static CBrush BrushList[] = { CBrush(ClrList[0]), ... }初始化代码,在旧版本C++标准下,语法层面要求数组初始化必须调用拷贝构造函数,把临时CBrush对象拷贝到数组内存中,哪怕编译器会做复制消除,也要求拷贝构造函数必须存在且可访问,因此触发了报错。
可行解决方案
- 方案1:改用指针数组存储
CBrush实例
把数组定义改为CBrush*类型,每个元素动态构造,避免拷贝操作:
static CBrush* BrushList[] = { new CBrush(ClrList[0]), new CBrush(ClrList[1]), new CBrush(ClrList[2]), new CBrush(ClrList[3]), new CBrush(ClrList[4]), new CBrush(ClrList[5]), new CBrush(ClrList[6]), new CBrush(ClrList[7]) };
后续使用时直接通过指针访问即可,程序退出前记得手动delete每个元素释放资源,避免GDI资源泄漏。
- 方案2:延迟初始化,先声明空数组再逐个初始化
CBrush提供了默认构造函数,你可以先定义空的CBrush数组,再调用CreateSolidBrush接口逐个初始化:
static CBrush BrushList[8]; // 初始化代码放在项目的初始化逻辑位置(比如窗口初始化函数内) for (int i = 0; i < 8; i++) { BrushList[i].CreateSolidBrush(ClrList[i]); }
该方案不需要手动释放资源,CBrush析构时会自动释放持有的GDI句柄。
- 方案3:升级编译标准到C17及以上
C17引入了强制复制消除规则,这种纯右值初始化数组的场景不需要拷贝构造函数存在,会直接在数组内存上构造对象。你可以在项目属性的「C/C++ -> 语言 -> C++语言标准」中选择ISO C++17 标准 (/std:c++17)或更高版本,重新编译即可通过。
内容的提问来源于stack exchange,提问作者Max Morgunov
相关产品推荐
相关产品推荐

