I have a std::queue
that is wrapped as a templated class to make a thread-safe queue. I have two versions of this class: one that stores value types, one that stores pointer types.
我有一个std::queue,它被包装成一个模板类来创建一个线程安全的队列。这个类有两个版本:一个存储值类型,一个存储指针类型。
For the pointer type, I'm having trouble deleting the elements of the queue on destruction. The reason is that I don't know a way to remove the items from the queue safely.
对于指针类型,我在销毁时无法删除队列的元素。原因是我不知道如何安全地从队列中删除这些项。
This reference states (vacuously, so I guess it doesn't actually STATE it) that the only way to remove elements from the queue is to call pop()
. The reference also says that pop()
calls the destructor for the item.
这个引用声明(真空地,我猜它实际上并没有声明),从队列中删除元素的唯一方法是调用pop()。引用还说pop()调用该项目的析构函数。
Well, this causes problems with my pointer types because they may or may not actually point to aggregates. If one of them points to an aggregate, they all will, but because the wrapper is templated, there is no guarantee which type (aggregated or non-aggregated) we are dealing with.
这导致指针类型出现问题,因为它们可能指向聚合,也可能不指向聚合。如果其中一个指向聚合,它们都会指向聚合,但是因为包装器是模板化的,所以不能保证我们要处理的类型(聚合或非聚合)。
So, when pop()
calls the destructor, what happens? How do I ensure that everything is being removed and the memory deallocation properly?
当pop()调用析构函数时,会发生什么?如何确保删除所有内容并正确释放内存?
Lastly, my solution is using an older version of GCC for ARM9. I don't have control over this. I understand that there are libraries that have smart pointers and containers that would assist here, but they are off-limits for me.
最后,我的解决方案是为ARM9使用旧版本的GCC。我无法控制这个。我知道有一些库有智能指针和容器可以在这里提供帮助,但是它们对我来说是禁止的。
3 个解决方案
#1
13
Online sources are worth what you pay for them - get a proper reference like Josuttis's book. pop() does not "call the destructor" - it simply removes an element from the queue adaptor's underlying representation (by default a std::deque) by calling pop_front() on it. If the thing being popped has a destructor, it will be used when the popped object goes out of scope, but the queue class has nothing to do with it.
网上资源是值得你为他们付出的-得到一个适当的参考,如Josuttis的书。pop()并不“调用析构函数”——它只是通过调用pop_front()从队列适配器的底层表示(默认情况下是std::deque)中删除一个元素。如果弹出的对象具有析构函数,那么当弹出的对象超出范围时将使用它,但是队列类与它没有任何关系。
#2
30
Pointers themselves don't actually have destructors, so calling pop()
on a queue containing a pointer won't call the destructor of the object your pointer points to.
指针本身实际上没有析构函数,所以在包含指针的队列上调用pop()不会调用指针指向的对象的析构函数。
#3
1
"How do I ensure that everything is being removed and the memory deallocation properly?"
“我如何确保所有东西都被删除,并正确地释放内存?”
If you absolutely have to store pointers in your queue, and you want them to be automatically freed when they're pop
ed, then instead of a queue of pointers, you need a queue of objects which store a pointer, and delete it in their destructor. You could for example use a queue of shared_ptr. shared_ptr isn't in the standard library, but it's part of TR1 and is widely available.
如果您必须在队列中存储指针,并且希望在弹出时自动释放指针,那么您需要一个对象队列来存储指针,并在其析构函数中删除指针。例如,可以使用shared_ptr队列。shared_ptr不在标准库中,但它是TR1的一部分,并且广泛可用。
Otherwise, it's the responsibility of the caller to delete the object:
否则,调用者有责任删除对象:
T *off = q.front();
q.pop();
delete off;
The summary is that containers of pointers to dynamically allocated objects are a bit awkward. If you can design your program so that containers store copies of your objects, instead of pointers to dynamic objects, then do so. Failing that, you're responsible for resource ownership, not the container. STL containers know nothing about ownership, they just copy and destroy their value_type
. Copying and destroying pointers does nothing to the objects they point to.
总结是,指向动态分配对象的指针的容器有些笨拙。如果您可以设计您的程序,以便容器存储您的对象的副本,而不是指向动态对象的指针,那么就这样做。否则,您将负责资源所有权,而不是容器。STL容器对所有权一无所知,它们只是复制并销毁自己的value_type。复制和销毁指针对它们指向的对象没有任何作用。
#1
13
Online sources are worth what you pay for them - get a proper reference like Josuttis's book. pop() does not "call the destructor" - it simply removes an element from the queue adaptor's underlying representation (by default a std::deque) by calling pop_front() on it. If the thing being popped has a destructor, it will be used when the popped object goes out of scope, but the queue class has nothing to do with it.
网上资源是值得你为他们付出的-得到一个适当的参考,如Josuttis的书。pop()并不“调用析构函数”——它只是通过调用pop_front()从队列适配器的底层表示(默认情况下是std::deque)中删除一个元素。如果弹出的对象具有析构函数,那么当弹出的对象超出范围时将使用它,但是队列类与它没有任何关系。
#2
30
Pointers themselves don't actually have destructors, so calling pop()
on a queue containing a pointer won't call the destructor of the object your pointer points to.
指针本身实际上没有析构函数,所以在包含指针的队列上调用pop()不会调用指针指向的对象的析构函数。
#3
1
"How do I ensure that everything is being removed and the memory deallocation properly?"
“我如何确保所有东西都被删除,并正确地释放内存?”
If you absolutely have to store pointers in your queue, and you want them to be automatically freed when they're pop
ed, then instead of a queue of pointers, you need a queue of objects which store a pointer, and delete it in their destructor. You could for example use a queue of shared_ptr. shared_ptr isn't in the standard library, but it's part of TR1 and is widely available.
如果您必须在队列中存储指针,并且希望在弹出时自动释放指针,那么您需要一个对象队列来存储指针,并在其析构函数中删除指针。例如,可以使用shared_ptr队列。shared_ptr不在标准库中,但它是TR1的一部分,并且广泛可用。
Otherwise, it's the responsibility of the caller to delete the object:
否则,调用者有责任删除对象:
T *off = q.front();
q.pop();
delete off;
The summary is that containers of pointers to dynamically allocated objects are a bit awkward. If you can design your program so that containers store copies of your objects, instead of pointers to dynamic objects, then do so. Failing that, you're responsible for resource ownership, not the container. STL containers know nothing about ownership, they just copy and destroy their value_type
. Copying and destroying pointers does nothing to the objects they point to.
总结是,指向动态分配对象的指针的容器有些笨拙。如果您可以设计您的程序,以便容器存储您的对象的副本,而不是指向动态对象的指针,那么就这样做。否则,您将负责资源所有权,而不是容器。STL容器对所有权一无所知,它们只是复制并销毁自己的value_type。复制和销毁指针对它们指向的对象没有任何作用。