C ++ и Qt: это утечка памяти?(и общие вопросы) - PullRequest
3 голосов
/ 04 декабря 2011

Я в основном использовал C для программирования в последние 2 года (ранее немного Java) и решил изучать C ++, используя Qt Creator и библиотеки Qt.

У меня вопрос: не вызывает ли утечка памяти следующий код:

    // filename is a QStringListIterator
    // dir is a QDir
    while (filename.hasNext()) {
            QString came_from_file(dir.filePath(filename.next()));
            QFile file(came_from_file);
            file.open(QFile::ReadOnly);
            file.readLine();
            while (!file.atEnd()) {
                    QString line(file.readLine());
                    do_something_with_stuff(line, came_from_file);
            }
    }

В частности, я не уверен, что происходит с сгенерированной dir.filePath(filename.next()) QString. Ссылка на came_from_file или указатель теряется при копировании? Является ли он «скопированным» (я полагаю, что он никогда не изменялся до тех пор, пока не был изменен из-за природы копирования-записи-записи контейнеров Qt)? Должен ли я написать это по-другому, как QString match = dir.file...? Насколько я понимаю, это должно быть равно.

В документах Qt также говорится, что QFile собирается закрыть () файл, если необходимо, в деструкторе. Деструктор вызывается? Переменная действительно выходит из области видимости, но я все еще не уверен, имеет ли это место так называемый RAII.

Как бы я мог file указать на другой файл?

Если я передаю переменные, подобные этой, в функции (я предполагаю, что это по ссылке, так как функция do_something... определяется таким образом), а затем они выходят из области видимости, но включаются в QHash / QMap / QSet функция, что происходит? Удаляются ли они и контейнеры сходят с ума, или есть какая-то причудливая маленькая схема, такая как реф. считая за всем этим? Или значения просто скопированы?

Я понимаю, что подобные вопросы задавались ранее, но я не могу понять это в этом примере, прочитав их, поскольку они кажутся разными.

Если с кодом или моим пониманием что-то не так, поправьте меня. :)

Спасибо, Nanthiel

Ответы [ 2 ]

6 голосов
/ 04 декабря 2011

В частности, я не уверен, что происходит с сгенерированной dir.filePath(filename.next()) QString.

came_from_file является копией (если не RVO срабатывает) возвращаемого значения QDir::filePath, которое, в свою очередь, является временным объектом, который автоматически очищается. Нет необходимости присваивать его переменной.

Деструктор вызывается? Переменная выходит из области видимости

Когда объект выходит из области видимости, вызывается его деструктор, если только вы не используете небезопасные конструкции, такие как longjmp.

Как бы я указал file на другой файл?

Я не могу найти чистый способ сделать это в документации Qt для QFile. Я предлагаю вам просто объявить новый QFile для другого файла. Одна из возможностей сделать это и сохранить контроль над количеством открытых файлов - это использовать области действия:

{
    QFile file(some_path);
    // do stuff to file
}   // end of file's scope, so it will be closed

{
    QFile file(other_path);
}   // again, end of scope

OTOH, вы можете явно закрыть QFile, чтобы вы могли проверить его состояние после сброса / закрытия.

2 голосов
/ 04 декабря 2011

Когда код, который вы разместили, выходит из области видимости, деконструкторы вызывают объекты и все очищается. Вообще говоря, в C ++ единственное время, когда вам нужно беспокоиться об утечках памяти, это когда вы используете ключевое слово new или некоторую функцию, которая возвращает указатель на выделенный системой объект (например, контекст устройства в windows), и в этом случае вы бы должны использовать соответствующую систему очистки вызова.

В случае функций все аргументы приведены по значению, если они не указаны как ссылки или указатели. Ссылки используются в качестве аргументов функции чаще всего, чтобы предотвратить снижение производительности при копировании большого объекта в функцию. В большинстве случаев эти ссылки служат для предотвращения изменения значений передаваемых данных. Ссылка в C ++ очень похожа на указатель без синтаксиса грязного указателя.

void foo (полоса b); // по значению

void foo (const bar & b); // по const ref

void foo (bar & b); // по ref, непостоянный объект bar, где эта функция выполняет некоторое действие над переданным объектом bar, и результаты этого действия будут видны на исходном объекте bar.

...