当您通过some_queue.front()
获取指针,将其分配给另一个变量,然后调用some_queue.pop()
时会发生什么?谁应该清理内存?(我使用的是c++98,如果真的需要,我可以使用boost智能指针)
例如:(为什么这样做?或者不应该这样做?)
class SClass {
public:
SClass(int si): sInt(si){}
int getSInt(){ return sInt; }
private:
int sInt;
... // bunch of other complicated data types so copy might be slow
};
int main()
{
cout << "Hello World" << endl;
queue<SClass *> sq;
for(int i = 0; i < 10; i++){
SClass *sc = new SClass(i);
sq.push(sc);
}
SClass *s2 = NULL;
while(!sq.empty()){
s2 = sq.front();
sq.pop();
cout << s2->getSInt() << endl;
}
delete s2;
return 0;
}
此处的工作测试代码:http://cpp.sh/6z7ke
在您的例子中,queue
只管理指针本身,它对所指向的内存不做任何事情。在您的示例中,您泄漏了前九个SClass
,只删除了最后一个。
如果你不明确地需要,你就不应该动态分配你的对象。试试这个:
int main()
{
cout << "Hello World" << endl;
queue<SClass> sq;
for(int i = 0; i < 10; i++){
sq.push(i);
}
while(!sq.empty()){
SClass& s2 = sq.front();
cout << s2.getSInt() << endl;
sq.pop();
}
return 0;
}
在这种情况下,对象在push
进入队列时创建,在pop
进入队列时销毁。如果我们忽略可能的性能问题(创建一个临时SClass
作为queue.push()
的参数,并将其复制到队列内部缓冲区;这是可以优化的,但这是另一个主题),这是一种更干净、可读的方法。
如果您的对象很大,并且您希望确保它们不会被无用地复制,那么您应该使用std::queue<std::unique_ptr<SClass>>
或为SClass
提供移动构造函数。这有点超出了范围,所以如果需要的话,我会让你再问一个问题。
当您通过some_queue.front()获取指针,将其分配给另一个变量,然后调用some_queue.pop()时,会发生什么?
对象的副本存储在另一个变量中,并从队列顶部删除。
谁应该清理内存?
谁分配了内存。
为什么这样做?
乍一看,它似乎没有任何理由不起作用。但是,您确实泄漏了大部分已分配的SClass
对象(除底部对象外的所有对象)。要修复泄漏,请删除从队列中获得的指针,然后再将其重新分配给另一个值(在循环结束时)。更好的是,不要手动分配内存,而是使用对象队列而不是指针队列。
std::queue::pop()
不会释放内存。在所有标准容器的情况下,用户必须确保释放原始指针所拥有的内存。
while(!sq.empty()){
s2 = sq.front();
sq.pop();
cout << s2->getSInt() << endl;
// memory should be freed here
delete s2;
}