melt日記

.NETすらまともに扱えないへたれのページ

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  111  : 記事  3  : コメント  8268  : トラックバック  41

ニュース

わんくま同盟

わんくま同盟

C# と VB.NET の質問掲示板

iKnow!


Dictation



書庫

2008年4月22日 #

std::stack<> を使うたびにいつも思うのですが、何で pop() の戻り値は void になっているのでしょうか?

このせいでわざわざ top() で先頭の値を持ってきて一時変数に確保した後 pop() を実行する必要があります。

std::stack<int> st;
st.push(10);

// int n = st.pop(); // こうやって書くことが出来ない
int n = st.top();
st.pop();

これについてずっと不満を覚えていたのですが、最近 Exceptional C++ を読んで、なぜ void になっているのか、というのを知りました。


pop() が void になっている理由は、例外安全を保証するためだそうです。


例えば T を返す pop() メソッドの実装は、次のように書くことが出来ます。

T pop()
{
    assert(size_ > 0);

    size_t index = size_ - 1; // 1

    T value = ptr_[index];    // 2
    Destruct(&ptr_[index]);   // 3
    size_--;                  // 4
    return value;             // 5

}

T のコピーコンストラクタが例外を投げる可能性がある場合、2 と 5 で例外が発生する可能性があります。

例外が発生しても呼び出し前の状態を保持する程度の安全性を保証する場合、例えば 2 で例外が発生しても size_ は変更されていないので安全です。

しかし、5 で例外が発生した場合、size_ は既に変更されているので、これは例外安全とは言えません。


例外仕様は設計に影響します。

例外安全を考えると、std::stack<> が pop() で T を返すことは不可能なのです。

なので、pop() は void とし、T& を返す top() というメソッドでスタックの先頭への参照を返してもらう必要があるのです。



例外って難しいです...。

posted @ 11:46 | Feedback (50)