2017-02-18 13 views
2

std :: stack要素の破棄順序については保証はありますか?std :: stack要素の破棄順序

私は、一連のサービスのライフタイムを管理するクラスを持っています。サービスの相互依存関係が存在する可能性があるため、構築と破壊の順序は重要です。サービスは作成の逆の順序で破棄する必要があります。

私はこの目的でstd::stack<std::unique_ptr<Service>>を使用すると考えました。スタックがコンテナアダプタであることを知り、破壊セマンティクスに影響するかもしれないと推測したが、std :: stackの要素の破壊順序を保証するI couldn't find any documentation(page 800)を検索した。最後に

は、私は少しテストを書いた:予想通り

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に対して保証されていますか?それとも、明らかになるまでそれをポップする(明らかに簡単な)ステップを取るべきですか?デフォルトstackにより

+0

関連:http://stackoverflow.com/questions/2083603/stl-containers-element-destruction-orderこれは 'vector'、' list'と 'map'についてですが、私は推測します'stack'にも同じことが適用されます – user463035818

+0

I s awそれですが、 'stack'はアダプタなので、追加の動作を定義するのかどうか疑問に思っていました。 'queue'と' stack'の両方が 'deque'に依存していて、どちらも要素の破棄順序を指定していない場合、デフォルトの要素破棄順序は2つのうちの1つにとって驚くべきことです。 – Justin

+1

醜い回避策は、すべての要素を手動でポップすることです。実際には、 'stack'デストラクタを呼び出すよりもずっと効率が悪いと私は思いません。 – user463035818

答えて

3

はコンテナではありません。コンテナアダプタです。 stack<T>

template< 
    class T, 
    class Container = std::deque<T> 
> class stack; 

破壊セマンティクスがdeque<T>のものを次のようになります。それはあなたが実際に要素を格納するために使用するコンテナの2番目のパラメータとして取ります。しかし、これは、実際にあなたを助けるものではありません。なぜなら、破壊の順序がdeque<T>であるからです。実際、シーケンスコンテナのいずれにも指定されていません。

破壊の順序が重要である場合、あなたは2つのいずれかを行う必要がありますが:どちらか最初にその要素が最後に破壊する新しいコンテナ提供:

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(); 
     } 
    } 
}; 
3

が定義破壊順序を持たないdeque(23.6.6.1)

template <class T, class Container = deque<T>> 
class stack { 

dequeによって支えられています。

stackをサポートする単純なコンテナを実装することができます。back,push_back、およびpop_backを入力するだけで済みます。

関連する問題