是否有关于std::stack元素销毁顺序的保证?
我有一个类,负责管理一组服务的生命周期。由于可能存在服务相互依赖关系,因此构造和销毁的顺序很重要-应该以与创建服务相反的顺序销毁服务。
我以为我会为此目的使用std::stack<std::unique_ptr<Service>>
。我知道堆栈是容器适配器,并猜测这可能会影响其破坏语义,因此我进行了搜索,但I couldn't find any documentation(第800页)确保了std::stack元素的破坏顺序。
最后,我编写了一个小测试:
struct Squealer {
Squealer() {
static int instance_count = 0;
this->instance = ++instance_count;
}
~Squealer() {
std::cout << "Destroying instance " << instance << std::endl;
}
int instance;
};
int main(int argc, char *[] argv) {
{
std::stack<Squealer> squealers;
squealers.emplace();
squealers.emplace();
squealers.emplace();
}
std::cout << "...done" << std::endl;
}
结果符合预期:
Destroying instance 3
Destroying instance 2
Destroying instance 1
...done
我应该依靠这种行为吗?是为std::stack保证了天真的销毁顺序,还是我应该采取将其弹出直到明确的步骤(非常简单)?
最佳答案
std::stack
不是容器,而是容器适配器。它以您实际上要使用哪个容器存储元素作为第二个参数:
template<
class T,
class Container = std::deque<T>
> class stack;
stack<T>
的销毁语义将是deque<T>
的销毁语义。但是,这并没有真正帮助您,因为deque<T>
的销毁顺序未由标准指定。实际上,没有为任何序列容器指定它。如果销毁顺序很重要,那么您应该执行以下两项操作之一:提供一个新容器,该容器首先销毁其元素:
template <class T>
struct my_deque : std::deque<T>
{
using std::deque<T>::deque;
~my_deque() {
while (!this->empty()) this->pop_back();
}
};
template <class T>
using my_stack = std::stack<T, my_deque<T>>;
或提供自己的
stack
实现,其析构函数弹出所有元素:template <class T, class Container = std::deque<T>>
struct ordered_stack : std::stack<T, Container>
{
using std::stack<T, Container>::stack;
~ordered_stack() {
while (!this->empty()) {
this->pop();
}
}
};