创建对象并防止销毁:RmgController存入QList后值丢失问题
解决QList中对象值被析构清空的问题
我来帮你分析下这个问题的根源,以及对应的解决方案:
问题本质
你遇到的情况,核心原因大概率是**RmgController类的拷贝/移动语义有问题**,或者你的析构函数做了超出职责范围的操作:
当你把局部创建的RmgController rmg对象push_back到QList时,QList会生成这个对象的副本(或者移动它,取决于C++版本和类的定义)。但如果你的类存在以下情况,就会导致列表里的副本数据被清空:
- 析构函数错误地清空了所有成员变量(包括值类型成员)
- 类持有动态资源但没有实现深拷贝,导致浅拷贝后原对象析构时释放了共享资源
具体解决方案
1. 先检查RmgController的析构函数
首先排查析构函数的逻辑,它只应该负责释放动态分配的资源(比如new出来的对象、打开的文件句柄等),而不是清空普通的数值/字符串成员。比如下面是错误的写法:
~RmgController() { // 错误:清空了值类型成员,导致局部对象析构时看似"清空"了数据 this->id = 0; this->name.clear(); // 或者错误delete了非动态分配的指针 }
正确的析构函数应该只处理资源释放:
~RmgController() { delete m_dynamicResource; // 仅释放动态分配的资源 }
2. 确保类具备正确的拷贝/移动语义
如果RmgController包含指针、动态数组等需要独占的资源,默认的拷贝构造函数会执行浅拷贝——也就是副本和原对象共享同一份资源。当局部的rmg对象析构时,资源被释放,列表里的副本就会变成悬空状态,看起来像是值被清空了。
解决方法:
- 实现深拷贝的拷贝构造函数和赋值运算符:
class RmgController { public: // 拷贝构造函数 RmgController(const RmgController& other) { // 对动态资源进行深拷贝 m_dynamicResource = new SomeClass(*other.m_dynamicResource); // 值类型成员直接拷贝即可 m_id = other.m_id; m_name = other.m_name; } // 赋值运算符(遵循拷贝交换惯用法更简洁) RmgController& operator=(RmgController other) { std::swap(m_dynamicResource, other.m_dynamicResource); std::swap(m_id, other.m_id); std::swap(m_name, other.m_name); return *this; } // 推荐:实现移动语义(C++11+),避免不必要的拷贝 RmgController(RmgController&& other) noexcept { m_dynamicResource = other.m_dynamicResource; other.m_dynamicResource = nullptr; // 转移资源所有权 m_id = std::move(other.m_id); m_name = std::move(other.m_name); } ~RmgController() { delete m_dynamicResource; } };
3. 使用emplace_back避免局部对象的创建
如果你使用的Qt版本支持C++11及以上(Qt 5.x基本都支持),可以用QList::emplace_back()直接在列表内部构造对象,跳过局部对象的创建和拷贝/移动步骤,从根源上避免析构问题:
void ListOfControllers::fromJson(QJsonObject obj) { rmgControllers.clear(); // 假设你遍历的是JSON数组,比如obj["controllers"].toArray() for (const QJsonValue& val : obj["controllers"].toArray()) { QJsonObject ctrlObj = val.toObject(); // 直接在列表末尾构造RmgController对象 rmgControllers.emplace_back(); // 给刚构造的对象填充JSON值 rmgControllers.back().fillWithValues(ctrlObj); } }
注意这里需要修改fillWithValues方法,让它接收QJsonObject参数,这样才能直接给列表里的对象赋值。
4. 检查fillWithValues的实现
最后确认fillWithValues方法是不是正确地给对象的成员变量赋值,而不是修改了局部变量:
// 错误示例:修改的是局部变量,不是对象成员 void RmgController::fillWithValues(QJsonObject obj) { QString name = obj["name"].toString(); // 这是局部变量,不是this->name } // 正确写法: void RmgController::fillWithValues(QJsonObject obj) { m_id = obj["id"].toInt(); m_name = obj["name"].toString(); }
按照上面的步骤排查,应该就能解决列表里对象值被清空的问题了。
内容的提问来源于stack exchange,提问作者mammadalius
相关产品推荐
相关产品推荐

