是否有关于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保证了天真的破坏顺序,或者我应该采取(通常很容易)弹出它直到它清楚的步骤?
答案 0 :(得分:5)
std::stack
不是Container,它是一个容器适配器。它需要您实际想要用来存储元素的第二个参数:
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();
}
}
};
答案 1 :(得分:3)
默认情况下,stack
支持deque
(23.6.6.1)
template <class T, class Container = deque<T>>
class stack {
deque
没有定义的销毁订单。
但是,您可以实现一个支持stack
的简单容器,只需提供back
,push_back
和pop_back
。