std :: stack元素销毁顺序

时间:2017-02-18 18:40:20

标签: c++ c++11

是否有关于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保证了天真的破坏顺序,或者我应该采取(通常很容易)弹出它直到它清楚的步骤?

2 个答案:

答案 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的简单容器,只需提供backpush_backpop_back