C++ и Qt: это утечка памяти? (и общие вопросы)
Я в основном использовал 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 функцией, что происходит? Удаляются ли они и контейнеры сходят с ума, или есть какая-то причудливая маленькая схема, такая как реф. считать за все это? Или значения просто скопированы?
Я понимаю, что подобные вопросы задавались ранее, но я не могу понять это в этом примере, читая их, так как они кажутся разными.
Если что-то не так с кодом или моим пониманием, поправьте меня.:)
Спасибо, Нантхил
2 ответа
В частности, я не уверен, что происходит с сгенерированным
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
так что вы можете проверить его состояние после сброса / закрытия.
Когда код, который вы разместили, выходит из области видимости, деконструкторы вызывают объекты, и все очищается. Вообще говоря, в C++ единственное время, когда вам нужно беспокоиться об утечках памяти, это когда вы используете ключевое слово new или некоторую функцию, которая возвращает указатель на выделенный системой объект (например, контекст устройства в windows), и в этом случае вы бы должны использовать соответствующую систему очистки вызова.
В случае функций все аргументы являются значениями, если они не указаны в качестве ссылок или указателей. Ссылки чаще всего используются в качестве аргументов функции, чтобы предотвратить снижение производительности при копировании большого объема в функцию. В большинстве случаев эти ссылки являются постоянными, чтобы помешать вам изменить значения передаваемых данных. Ссылка в C++ очень похожа на указатель, без синтаксиса грязного указателя.
пустота foo(полоса b); // по значению
void foo(const bar& b); // по const ref
void foo(bar & b); // по ref, изменяемый объект bar, где эта функция выполняет некоторое действие над переданным объектом bar, и результаты этого действия будут видны на исходном объекте bar.