我创建了这个2D Qlist。代码“有效”,但当我考虑更深入的语法时,它让我想知道这段代码是否会导致内存泄漏。
如果有人能够了解这段代码是否会导致内存泄漏,我会很高兴。如果是的话,为什么以及如何解决?
我的具体问题是代码注释中标记为Q1,Q2,Q3,Q4的问题。
另外,我应该如何从lszq2DList中销毁一些行,最终应该如何销毁 lszq2DList。
//The 2d data sructure. Each row will be a QStringList.
QList<QStringList> lszq2DList;
//The variable "emptyTempList" is a concern to me.
//Q1:: Isn't "emptyTempList" just a pointer to some allocated place in memory?
//If so, I imagine it points to some data structure allocated in memory.
//Or does this not allocate anything? I have a feeling it does not.
QStringList emptyTempList; //I use it in my scheme to make a 2D data struct.
for(int i=0; i<3; i++){
//Q2: Because I am in a loop and reusing the same pointer "emptyTempList",
//aren't i pointing to the same thing?
//If I think about this, each item in my Qlist (each row) should be
//pointing to the same place in memory. To whatever "emptyTempList"
//points to.
//Of course, this is not the case. What is really going on in line bellow?
lszq2DList += emptyTempList; //I'm no really pointing to anything am I?
QString szqTempString; //Q3: Gets trashed when out of scope?
for(int j=0; j<3; j++){
szqTempString.clear();
szqTempString = "jazz";
//QString value gets copied into datastructure?
lszq2DList[i] += szqTempString;
}
}
QStringList emptyTempList2;
emptyTempList2 += "blues";
emptyTempList2 += "blues";
emptyTempList2 += "blues";
//I'll add another row.
lszq2DList += emptyTempList2;
//Q4: lszq2DList[3] does not point to emptyTempList2, right?
//Instead it copies all the strings
//from to emptyTempList2 to lszq2DList[3], right?
答案 0 :(得分:4)
QList,QStringList和QString都是“隐式共享”,基本上意味着“写入时复制”。例如:
QStringList someFunction() {
QStringList list;
QString str("Hello World!");
for(int x = 0;x < 100; ++x) {
list << str;
}
QStringList list2 = list;
QStringList list3 = list;
QStringList list4 = list;
return list4;
}
QStringList list5 = someFunction();
毕竟你还只有字符串“Hello World!”在记忆中一次。您可以阅读更多相关信息Here。作为Qt类的一般规则,“从QObject继承的对象进入堆,否则它们进入堆栈”。有异常,但很少和隐式共享的类应该总是在堆栈上。
答案 1 :(得分:3)
我建议使用与valgrind或其他类似的东西来检查内存泄漏。
然而,当内存“泄漏”时,这意味着在使用后该内存根本没有释放,并且所有访问都已被删除。这实际上意味着在堆上分配了内存,但是没有任何东西可以访问它,所以它实际上是无用的内存。例如,当您使用“new”动态地将内存分配给指针时,必须“删除”以释放内存。我举一个例子。
char * ptr = new char;
ptr = NULL; // Memory leak
delete ptr; // This is useless since it no longer points to the memory location
然而,这是完全有效的
char * ptr = new char;
delete ptr;
ptr = NULL;
第一个泄漏的原因是因为你没有“删除”内存。由于在调用delete之前指针位置已更改为“NULL”,因此在将设置为NULL之前,它不知道在指针与关联的任何地址处释放内存。
但是,它看起来并不像你的代码会有任何内存泄漏(没有动态分配)。由于看起来所有变量都在堆栈上分配,系统会为您管理这个内存 - 一旦这些对象超出范围(如果在main()
中,那么当程序退出时),它们将被弹出按系统排除堆栈。但是,假设QList没有泄漏。
修改强>
请记住,当您创建类的实例时,分配的内存位于堆栈上(内存在离开范围时立即释放),您无需担心。动态分配(使用new / delete分配/释放内存)存储在堆上(为了我们的目的,持久性内存)。因此,您不必担心没有动态分配的内存泄漏。
编辑2
关于使用堆与堆栈,尽可能使用堆栈。你需要管理的内存越少越好(并且你将会出现更少的错误)。就问题2而言,您没有使用指针。你正在做的是复制emptyTempList
的值而不是重用它的内存位置(因为它不是指针)。您必须使用&
运算符从对象中提取内存地址,因为它不是指针。
希望这有帮助!
的问候,
丹尼斯M。