C++ C2280错误:向vector添加Brick对象时引用已删除函数的排查与解决
C2280错误原因及修复方案
错误原因
std::vector::push_back向容器添加元素时,会调用元素类型的拷贝构造函数完成对象复制。你的Brick类包含XMLDocument类型成员mDoc,而TinyXML的XMLDocument类没有提供可访问的拷贝构造函数(或明确禁用了拷贝操作)。根据C++规则,当类包含无法拷贝的成员时,编译器会自动删除该类的拷贝构造函数与拷贝赋值运算符。执行brickArr.push_back(brick)时,尝试调用已被删除的Brick拷贝构造函数,触发C2280错误。
修复方案
方案1:使用智能指针存储对象(推荐)
将容器改为存储std::unique_ptr<Brick>,避免直接拷贝Brick对象:
- 修改
Bricks.h中容器定义:
std::vector<std::unique_ptr<Brick>> brickArr;
- 修改
Bricks.cpp中添加元素的代码:
brickArr.push_back(std::make_unique<Brick>(rowSpacing, columnsSpacing, (const char*)brickPlan[index], renderer));
智能指针的移动操作是合法的,容器存储指针而非对象,彻底规避拷贝问题。
方案2:为Brick类实现移动语义
若希望容器直接存储对象,可让Brick支持移动构造(前提是TinyXML的XMLDocument支持移动):
- 在
Brick.h中声明移动构造与移动赋值运算符:
Brick(Brick&&) noexcept; Brick& operator=(Brick&&) noexcept;
- 在
Brick.cpp中默认实现(若XMLDocument支持移动):
Brick::Brick(Brick&&) noexcept = default; Brick& Brick::operator=(Brick&&) noexcept = default;
- 修改
push_back调用为移动语义:
brickArr.push_back(std::move(brick));
方案3:重构XML加载逻辑(优化性能)
每个Brick构造时重复加载同一个XML文件是冗余操作,可将XML解析逻辑移到Bricks类中:
- 定义一个结构体存储砖块配置数据:
struct BrickData { int hitPoints; int breakScore; std::string texturePath; };
- 在
Bricks::Init中先加载XML,解析所有BrickType数据并存储到映射中:
std::unordered_map<std::string, BrickData> brickTypeMap; // 解析XML并填充brickTypeMap的逻辑
- 修改
Brick类,移除XMLDocument成员,构造函数直接接收BrickData:
Brick(int rowSpacing, int columnSpacing, const BrickData& data, SDL_Renderer* renderer);
- 创建
Brick时从映射中获取数据,避免每个砖块重复加载XML。
这种方案既解决了拷贝问题,又减少了IO操作,提升程序性能。
内容的提问来源于stack exchange,提问作者Swatheduru
相关产品推荐
相关产品推荐

