在过去的两年里,我主要使用C进行编程(以前是一些Java),并决定使用Qt Creator和Qt库来学习C ++。
我的问题是以下代码是否引入了内存泄漏:
// 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容器的Copy-On-Write性质)?我应该用不同的方式写出来,比如QString match = dir.file...
吗?据我了解,这应该是平等的。
它还在Qt文档中说QFile将在析构函数中关闭()文件。析构函数会被调用吗?该变量确实“超出了范围”,但我仍然不确定这是否是所谓的RAII。
如何让file
指向其他文件?
如果我将这样的变量传递给函数(我假设这是通过引用,因为函数do_something...
以这种方式定义),然后它们超出范围,但是被插入到QHash / QMap /中通过函数QSet,会发生什么?他们被删除了,容器变得疯狂,还是有一些像ref那样花哨的小方案。在这一切背后算吗?或者只是简单地复制了这些值?
我之前已经意识到类似的问题,但我似乎无法通过阅读它们来解释这个问题,因为它们似乎是不同的情况。
如果代码或我的理解有问题,请纠正我。 :)
谢谢, Nanthiel
答案 0 :(得分:6)
具体来说,我不确定生成的
dir.filePath(filename.next())
QString会发生什么。
came_from_file
是RVO的返回值的副本(除非QDir::filePath
开始),而longjmp
又是一个自动清理的临时对象。无需将其分配给变量。
析构函数是否被调用?变量确实“超出了范围”
当一个对象超出范围时,将调用它的析构函数,除非你使用像QFile
这样的不安全结构。
如何让
file
指向其他文件?
我在{{3}}的Qt文档中找不到干净的方法。我建议您为另一个文件声明一个新的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
,以便在刷新/关闭后检查其状态。
答案 1 :(得分:2)
当您发布的代码留下范围时,将在对象上调用解构器,并清除所有内容。一般来说,在C ++中,唯一需要担心内存泄漏的时候是使用new关键字,或者某个函数返回系统分配对象的指针(如Windows上的设备上下文),在这种情况下你会必须使用适当的系统清理电话。
对于函数,除非指定为引用或指针,否则所有参数都是按值的。引用最常用作函数参数,以防止必须将大对象复制到函数中而导致性能损失。大多数情况下,这些引用都是const,以防止您修改传入的数据的值.C ++中的引用与指针非常相似,没有凌乱的指针语法。
void foo(bar b); //按值
void foo(const bar& b); //由const ref
void foo(bar& b); //通过ref,一个可变的bar对象,此函数对您传入的bar对象执行某些操作,并且该操作的结果将在原始bar对象上可见。