我怎样才能 return 一个 QList<specificObject*> 指针并且没有内存泄漏?
How can I return a QList<specificObject*> pointer and get no memory leak?
我的数据库中有一个问题和一个答案 table。这两者之间的关系是一个问题可以有多个答案。在我的 C++ 代码中,我有一个 Question 普通对象,它存储问题文本和一个 QList 答案。 Answer 普通对象只存储答案文本。
我想阅读所有问题以及与这些问题相关的所有答案,并将它们存储在我的问题对象中。这就是我所做的。
QList<Question*> *ExamPersistance::readQuestions(int examId)
{
QList<Question*> *questions;
QSqlQuery *query = new QSqlQuery(connection->getDb());
query->prepare("select q.id, q.text from question q where id_exam =:examId");
query->bindValue(":examId",examId);
query->exec();
while(query->next())
{
questions->append(new Question(
query->value(1).toString(),
this->readAnswers(query->value(0).toInt())));
}
return questions;
}
QList<Answer*> *ExamPersistance::readAnswers(int questionId)
{
QList<Answer*> *answers;
QSqlQuery *query = new QSqlQuery(connection->getDb());
query->prepare("select a.text from answer a where id_question = :questionId");
query->bindValue(":questionId",questionId);
query->exec();
while(query->next())
{
answers->append(new Answer(query->value(0).toString()));
}
return answers;
}
我遇到分段错误,我不知道为什么。
这些是我的头文件中的构造函数
Answer(QString text);
Question(QString name, QList<Answer*> *answers);
也许我对指针做错了什么。我不得不承认我不是很熟悉这些因为我来自 Java.
编辑:
我还有一个 class "exam",它存储了某个考试的问题,但我认为这不重要。只是你知道这个 "int examId" 代表什么
您忘记初始化一些指针。
修复了崩溃和内存泄漏的版本:
QList<std::unique_ptr<Question>> ExamPersistance::readQuestions(int examId)
{
QList<std::unique_ptr<Question>> questions;
QSqlQuery query(connection->getDb());
query.prepare("select q.id, q.text from question q where id_exam =:examId");
query.bindValue(":examId",examId);
query.exec();
while(query.next())
{
questions.append(std::make_unique<Question>(
query.value(1).toString(),
this->readAnswers(query.value(0).toInt())));
}
return questions;
}
How can I return a QList pointer and get no memory
leak?
最简单且可能是最佳的方法是存储值而不是指针:
QList<Question> listOfQuestions;
QList<Answer> listOfAnswers;
此外,我们还可以制作共享指针的集合。但这不是那些在 QSharedPointer 上阅读的内容的预期用途。
QList<QSharedPointer<Question>> listOfQuestions;
QList<QSharedPointer<Answer>> listOfAnswers;
否则你需要弄清楚哪个对象负责释放你作为指针传递给列表的对象(通过提供 'parent' 指针非常流行的 Qt 技术)。
实际值列表:
QList<Question> ExamPersistance::readQuestions(int examId)
{
QList<Question> questions;
QSqlQuery query(connection->getDb());
query.prepare("select q.id, q.text from question q where id_exam =:examId");
query.bindValue(":examId",examId);
query.exec();
while(query.next())
{
questions.append(Question(
query.value(1).toString(),
this->readAnswers(query.value(0).toInt())));
}
return questions;
}
QList<Answer> ExamPersistance::readAnswers(int questionId)
{
QList<Answer> answers;
QSqlQuery query(connection->getDb());
query.prepare("select a.text from answer a where id_question = :questionId");
query.bindValue(":questionId",questionId);
query.exec();
while(query.next())
{
answers.append(Answer(query.value(0).toString()));
}
return answers;
}
当然要注意你的问题中看不到的实际构造函数参数。使用 C++ 11 和 'move' 构造函数应该非常有效。
您正在解除对 QList 指针的引用,但您从未对它们进行初始化(即它们指向垃圾)。此代码应该可以解决该问题。
QList<Question*> *ExamPersistance::readQuestions(int examId)
{
QList<Question*> *questions = new QList<Question*>();
QSqlQuery *query = new QSqlQuery(connection->getDb());
query->prepare("select q.id, q.text from question q where id_exam =:examId");
query->bindValue(":examId",examId);
query->exec();
while(query->next())
{
questions->append(new Question(
query->value(1).toString(),
this->readAnswers(query->value(0).toInt())));
}
return questions;
}
QList<Answer*> *ExamPersistance::readAnswers(int questionId)
{
QList<Answer*> *answers = new QList<Answer*>();
QSqlQuery *query = new QSqlQuery(connection->getDb());
query->prepare("select a.text from answer a where id_question = :questionId");
query->bindValue(":questionId",questionId);
query->exec();
while(query->next())
{
answers->append(new Answer(query->value(0).toString()));
}
return answers;
}
请注意,这只是我发现的问题。即使此代码运行,它也存在其他问题。您肯定会泄漏与变量 query 关联的内存,并且可能会泄漏所有 Questions 和 Answer 对象(以及我们正在处理的 QList)的内存,除非您稍后在某个时候删除它们。在 C++ 中,每次调用 new 时都需要调用 delete,否则会泄漏内存。除非您确实需要,否则在 C++ 中通常不赞成使用指针。这与必须使用 new 来创建对象的 Java 有很大不同。 answer 对 C++ 中 new 运算符和 Java 的区别进行了不错的讨论,是一个很好的起点。
我的数据库中有一个问题和一个答案 table。这两者之间的关系是一个问题可以有多个答案。在我的 C++ 代码中,我有一个 Question 普通对象,它存储问题文本和一个 QList 答案。 Answer 普通对象只存储答案文本。
我想阅读所有问题以及与这些问题相关的所有答案,并将它们存储在我的问题对象中。这就是我所做的。
QList<Question*> *ExamPersistance::readQuestions(int examId)
{
QList<Question*> *questions;
QSqlQuery *query = new QSqlQuery(connection->getDb());
query->prepare("select q.id, q.text from question q where id_exam =:examId");
query->bindValue(":examId",examId);
query->exec();
while(query->next())
{
questions->append(new Question(
query->value(1).toString(),
this->readAnswers(query->value(0).toInt())));
}
return questions;
}
QList<Answer*> *ExamPersistance::readAnswers(int questionId)
{
QList<Answer*> *answers;
QSqlQuery *query = new QSqlQuery(connection->getDb());
query->prepare("select a.text from answer a where id_question = :questionId");
query->bindValue(":questionId",questionId);
query->exec();
while(query->next())
{
answers->append(new Answer(query->value(0).toString()));
}
return answers;
}
我遇到分段错误,我不知道为什么。
这些是我的头文件中的构造函数
Answer(QString text);
Question(QString name, QList<Answer*> *answers);
也许我对指针做错了什么。我不得不承认我不是很熟悉这些因为我来自 Java.
编辑:
我还有一个 class "exam",它存储了某个考试的问题,但我认为这不重要。只是你知道这个 "int examId" 代表什么
您忘记初始化一些指针。
修复了崩溃和内存泄漏的版本:
QList<std::unique_ptr<Question>> ExamPersistance::readQuestions(int examId)
{
QList<std::unique_ptr<Question>> questions;
QSqlQuery query(connection->getDb());
query.prepare("select q.id, q.text from question q where id_exam =:examId");
query.bindValue(":examId",examId);
query.exec();
while(query.next())
{
questions.append(std::make_unique<Question>(
query.value(1).toString(),
this->readAnswers(query.value(0).toInt())));
}
return questions;
}
How can I return a QList pointer and get no memory leak?
最简单且可能是最佳的方法是存储值而不是指针:
QList<Question> listOfQuestions;
QList<Answer> listOfAnswers;
此外,我们还可以制作共享指针的集合。但这不是那些在 QSharedPointer 上阅读的内容的预期用途。
QList<QSharedPointer<Question>> listOfQuestions;
QList<QSharedPointer<Answer>> listOfAnswers;
否则你需要弄清楚哪个对象负责释放你作为指针传递给列表的对象(通过提供 'parent' 指针非常流行的 Qt 技术)。
实际值列表:
QList<Question> ExamPersistance::readQuestions(int examId)
{
QList<Question> questions;
QSqlQuery query(connection->getDb());
query.prepare("select q.id, q.text from question q where id_exam =:examId");
query.bindValue(":examId",examId);
query.exec();
while(query.next())
{
questions.append(Question(
query.value(1).toString(),
this->readAnswers(query.value(0).toInt())));
}
return questions;
}
QList<Answer> ExamPersistance::readAnswers(int questionId)
{
QList<Answer> answers;
QSqlQuery query(connection->getDb());
query.prepare("select a.text from answer a where id_question = :questionId");
query.bindValue(":questionId",questionId);
query.exec();
while(query.next())
{
answers.append(Answer(query.value(0).toString()));
}
return answers;
}
当然要注意你的问题中看不到的实际构造函数参数。使用 C++ 11 和 'move' 构造函数应该非常有效。
您正在解除对 QList 指针的引用,但您从未对它们进行初始化(即它们指向垃圾)。此代码应该可以解决该问题。
QList<Question*> *ExamPersistance::readQuestions(int examId)
{
QList<Question*> *questions = new QList<Question*>();
QSqlQuery *query = new QSqlQuery(connection->getDb());
query->prepare("select q.id, q.text from question q where id_exam =:examId");
query->bindValue(":examId",examId);
query->exec();
while(query->next())
{
questions->append(new Question(
query->value(1).toString(),
this->readAnswers(query->value(0).toInt())));
}
return questions;
}
QList<Answer*> *ExamPersistance::readAnswers(int questionId)
{
QList<Answer*> *answers = new QList<Answer*>();
QSqlQuery *query = new QSqlQuery(connection->getDb());
query->prepare("select a.text from answer a where id_question = :questionId");
query->bindValue(":questionId",questionId);
query->exec();
while(query->next())
{
answers->append(new Answer(query->value(0).toString()));
}
return answers;
}
请注意,这只是我发现的问题。即使此代码运行,它也存在其他问题。您肯定会泄漏与变量 query 关联的内存,并且可能会泄漏所有 Questions 和 Answer 对象(以及我们正在处理的 QList)的内存,除非您稍后在某个时候删除它们。在 C++ 中,每次调用 new 时都需要调用 delete,否则会泄漏内存。除非您确实需要,否则在 C++ 中通常不赞成使用指针。这与必须使用 new 来创建对象的 Java 有很大不同。 answer 对 C++ 中 new 运算符和 Java 的区别进行了不错的讨论,是一个很好的起点。