std :: stack元素销毁顺序

Jus*_*tin 3 c++ c++11

是否有关于std :: stack元素销毁顺序的保证?

我有一堂课,负责管理一组服务的生命周期。由于可能存在服务相互依赖关系,因此构建和销毁的顺序很重要-应该以与创建服务相反的顺序销毁服务。

我以为我会std::stack<std::unique_ptr<Service>>为此目的使用。我搜索了堆栈,并知道它可能会影响其销毁语义,因此我搜索了一下,但是找不到任何文档(第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;
}
Run Code Online (Sandbox Code Playgroud)

结果符合预期:

Destroying instance 3
Destroying instance 2
Destroying instance 1
...done
Run Code Online (Sandbox Code Playgroud)

我应该依靠这种行为吗?是为std :: stack保证了天真的销毁顺序,还是我应该采取(显然很容易的)弹出步骤直到明确为止?

Bar*_*rry 5

std::stack不是容器,而是容器适配器。它以您实际要使用哪个容器存储元素作为第二个参数:

template<
    class T,
    class Container = std::deque<T>
> class stack;
Run Code Online (Sandbox Code Playgroud)

的销毁语义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>>;
Run Code Online (Sandbox Code Playgroud)

或提供自己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();
        }
    }
};
Run Code Online (Sandbox Code Playgroud)