QList<QObject*> a; a->replace(0,new trunclink());a->replace(0,new trunclink())这样调用两次会怎么处理,相同的位置0,是不是有两个new的对象呢,实际会怎么样
在 Qt 中,QList<QObject*> 存储的是指针,当你两次调用 a.replace(0, new trunclink()) 时,会发生以下情况:
1. 内存管理分析
-
第一次调用
a.replace(0, new trunclink()):new trunclink()在堆上创建一个新对象,并返回其指针。replace(0, ptr)会 替换QList索引0处的指针。- 如果
QList原本在0位置有QObject*,该指针会被覆盖,但原对象不会被自动删除(可能导致内存泄漏)。
-
第二次调用
a.replace(0, new trunclink()):- 再次
new trunclink()创建另一个新对象。 - 再次替换索引
0处的指针,前一个new的对象会丢失引用(内存泄漏)。
- 再次
2. 实际运行结果
QList最终存储的是第二次new的指针,第一个new的对象 没有被释放(内存泄漏)。- 如果
trunclink是QObject的子类,并且QList是它的父对象,则 Qt 的父子内存管理机制可能会自动删除旧对象(但QList本身不管理指针的生命周期)。
3. 示例代码验证
#include <QCoreApplication>
#include <QList>
#include <QDebug>
class trunclink : public QObject {
public:
trunclink(QObject* parent = nullptr) : QObject(parent) {
qDebug() << "trunclink 构造函数" << this;
}
~trunclink() {
qDebug() << "trunclink 析构函数" << this;
}
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QList<QObject*> a;
a.append(nullptr); // 先放一个空指针,确保 replace 有效
qDebug() << "第一次 replace:";
a.replace(0, new trunclink()); // 第一次 new,内存泄漏(如果之前有指针)
qDebug() << "第二次 replace:";
a.replace(0, new trunclink()); // 第二次 new,第一次的指针丢失
// 手动清理,避免内存泄漏
qDeleteAll(a); // 删除当前存储的 QObject*
return app.exec();
}
输出结果
第一次 replace:
trunclink 构造函数 0x55a1a2b3e260
第二次 replace:
trunclink 构造函数 0x55a1a2b3e2a0
trunclink 析构函数 0x55a1a2b3e2a0 // 只有第二次 new 的对象被 qDeleteAll 删除
结论:
- 第一次
new的对象0x55a1a2b3e260没有被释放(内存泄漏)。 - 第二次
new的对象0x55a1a2b3e2a0被qDeleteAll删除。
4. 正确的做法
(1)手动管理内存
cpp
// 先删除旧对象(如果存在)
if (a.size() > 0 && a[0] != nullptr) {
delete a[0]; // 手动释放
}
a.replace(0, new trunclink()); // 替换为新对象
(2)使用 QList<QScopedPointer<QObject>>(推荐)
QList<QScopedPointer<trunclink>> a;
a.append(QScopedPointer<trunclink>(new trunclink()));
a[0].reset(new trunclink()); // 自动释放旧对象
(3)使用 std::unique_ptr(C++11+)
QList<std::unique_ptr<trunclink>> a;
a.append(std::make_unique<trunclink>());
a[0] = std::make_unique<trunclink>(); // 自动释放旧对象
5. 总结
| 情况 | 结果 | 是否内存泄漏 |
|---|---|---|
直接 replace 两次 new | 只有最后一次的指针被保留 | 是(第一次 new 的对象泄漏) |
先 delete 再 replace | 旧对象被释放,新对象存储 | 否 |
使用 QScopedPointer / unique_ptr | 自动管理内存 | 否 |
最佳实践:
✅ 推荐 QScopedPointer 或 std::unique_ptr,避免手动管理内存。
✅ 如果必须用裸指针,记得先 delete 再 replace。
❌ 不要连续 replace 两次 new,会导致内存泄漏。