[英]How can I return a QList<specificObject*> pointer and get no memory leak?
我的數據庫中有一個問題和一個答案表。 兩者之間的關系是一個問題可以有多個答案。 在我的C ++代碼中,我有一個Question普通對象,該對象存儲問題文本和答案的QList。 答案普通對象僅存儲答案文本。
我想閱讀所有問題以及與這些問題相關的所有答案,並將其存儲在我的問題對象中。 這就是我所做的。
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,所以對這些知識不是很熟悉。
編輯:
我也有一個“考試”課程,它存儲有關特定考試的問題,但我並不認為這很重要。 只是您知道此“ intexamId”代表什么
我如何返回QList指針並且沒有內存泄漏?
最簡單且可能最佳的方法是存儲值而不是指針:
QList<Question> listOfQuestions;
QList<Answer> listOfAnswers;
另外,我們可以收集共享指針。 但這不是在QSharedPointer上閱讀的內容的預期用途。
QList<QSharedPointer<Question>> listOfQuestions;
QList<QSharedPointer<Answer>> listOfAnswers;
否則,您需要找出哪個對象負責釋放作為指針傳遞給您的對象(通過提供“父”指針非常流行的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<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;
}
您正在取消引用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;
}
請注意,這只是我發現的問題。 即使該代碼運行,它也會有其他問題。 您肯定會泄漏與變量查詢關聯的內存,並且可能會將內存泄漏給所有Questions和Answer對象(以及我們正在使用時的QList),除非您稍后刪除它們。 在C ++中,您需要為每個對new的調用都調用delete,否則您將泄漏內存。 除非確實需要,否則在C ++中通常不使用指針。 這與Java必須使用new創建對象的Java完全不同。 這個答案對C ++和Java中new運算符的區別進行了不錯的討論,並且是一個很好的起點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.