簡體   English   中英

如何返回QList <specificObject*> 指針並沒有內存泄漏?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM