为什么 std::sort 在使用 QList 时崩溃?

Why does std::sort crash when working with a QList?

本文关键字:QList 崩溃 std sort 为什么      更新时间:2023-10-16

我在运行以下代码时遇到几次不同的崩溃,有时是分段错误,有时是ASSERT: "&other != this" in file C:/Qt/5.12.3/mingw73_64/include/QtCore/qstring.h, line 958

重现此内容的代码如下。

#include <QList>
#include <QDebug>
class Tag
{
public:
Tag(const QString& name)
{
this->name = new QString(name);
}
Tag(const Tag& tag)
{
this->name = new QString(tag.getName());
}
~Tag()
{
if (name != nullptr) delete name;
}
QString getName() const
{
return *name;
}
static bool sortByName(const Tag& t1, const Tag& t2)
{
return t1.getName() < t2.getName();
}
private:
QString* name;
};
int main(int argc, char **argv)
{
QList<Tag> tags;
Tag a("a");
Tag b("b");
Tag c("c");
Tag d("d");
Tag e("e");
tags << e << c << a << b << d;
qDebug() << "before sorting";
for (Tag tag : tags) {
qDebug() << tag.getName();
}
std::sort(tags.begin(), tags.end(), Tag::sortByName);
qDebug() << "after sorting";
for (Tag tag : tags) {
qDebug() << tag.getName();
}
return 0;
}

我注意到,如果初始QList充满了指向Tag对象的指针,并且sortByName()更改为接受指针,则不会导致问题。我不知道为什么。

问题的根源是您使用原始指针作为成员变量(名称(,并尝试显式执行手动分配/复制而不满足 3 规则。sort调用复制赋值运算符并获取默认实现 - 即盲目复制指针值。 因此,双重删除和崩溃...

最简单的解决方法是仅将name从指针更改为具体实例。

也就是说,这可以编译并与您已经提供的main正常工作。

class Tag
{
public:
Tag(const QString& name) : _name(name)
{
}
const QString& getName() const
{
return _name;
}
static bool sortByName(const Tag& t1, const Tag& t2)
{
return t1.getName() < t2.getName();
}
private:
QString _name;
};

如果确实需要将name保留为指针,请将复制赋值运算符方法添加到 Tag 类中:

class Tag
{
…
Tag& operator=(const Tag& t)
{
Qstring* oldName = this->name;
this->name = new QString(t.getName());
delete oldName;
return *this;
}
};