1. ホーム
  2. c++

[解決済み] なぜ std::queue::pop は値を返さないのでしょうか?

2022-04-28 01:50:58

質問

私はこのような ページ しかし、私は同じの理由を得ることができません。そこには次のように書かれています。

"値を全く返さない方が合理的であり クライアントがキューの先頭にある値を検査するために front() を使用することです。

しかし、front() から要素を検査するには、その要素を lvalue にコピーする必要もありました。たとえば、次のようなコード・セグメントがあります。

std::queue<int> myqueue;
int myint;
int result;
std::cin >> myint;
myqueue.push (myint);

/* ここで、RHSにtemporaryが作成され、resultに割り当てられます。 参照で返す場合は、ポップ操作の後に結果が無効になる */

result = myqueue.front();  //result.
std::cout << ' ' << result;
myqueue.pop();

5行目に カウト オブジェクトはまず myqueue.front() のコピーを作成し、それを result に代入しています。つまり、ポップ関数でも同じことができるのです。

解決方法は?

<ブロッククオート

では、何が違うのでしょうか。ポップアップ関数でも同じことができたはずです。

確かに同じことができたかもしれません。そうしなかった理由は、ポップした要素を返すポップは例外がある場合には安全でないからです(値で返す必要があるため、コピーを作成することになります)。

次のようなシナリオを考えてみましょう(私が言いたいことを説明するために、素朴で作り込まれたポップの実装を使用します)。

template<class T>
class queue {
    T* elements;
    std::size_t top_position;
    // stuff here
    T pop()
    {
        auto x = elements[top_position];
        // TODO: call destructor for elements[top_position] here
        --top_position;  // alter queue state here
        return x;        // calls T(const T&) which may throw
    }

T のコピーコンストラクタが return で投げる場合、キューの状態はすでに変更されています ( top_position 私の素朴な実装では)その要素はキューから削除され、返されません。どう考えても(クライアントコードでどのように例外をキャッチしても)キューの先頭の要素は失われています。

この実装は、ポップした値が不要な場合にも非効率です(つまり、誰も使わない要素のコピーを作ってしまう)。

これを安全かつ効率的に実装するためには、2つの別々の操作( void popconst T& front() ).