3

Java では、返された要素を実際に返す end の削除メソッドDequeがクラスにあります。C++ では、同じ動作を実現する唯一の方法は、最初に要素を明示的にコピーしてからポップすることです。

std::deque<int> myDeque;
myDeque.push_back(5);

int element = myDeque.back();
myDeque.pop_back();

両方を同時に行うメカニズムはありますか?

4

3 に答える 3

11

独自のラッパー関数テンプレートを作成できます。

// Precondition: !container.empty()
// Exception safety: If there is an exception during the construction of val,
//                   the container is not changed.
//                   If there is an exception during the return of the value,
//                   the value is lost.
template <typename C>
auto back_popper(C & container) -> decltype(container.back())
{
    auto val(std::move(container.back()));
    container.pop_back();
    return val;
}

使用法:

auto element = back_popper(myDeque);

back()そもそもandの分離の動機となる根本的な問題を回避することはできません。pop_back()つまり、要素のコピーまたは移動コンストラクターが例外をスローする可能性があり、これが発生するとポップされた要素が失われる可能性があります。スローしないオブジェクト、たとえば a を返すことでケースバイケースで軽減できますがunique_ptr、これは動的割り当ての要素を失うリスクと引き換えになりますが、明らかにそれはあなたがしなければならない個人的な選択です。あなたのためにはなりません。

例えば:

// Guarantees that you either get the last element or that the container
// is not changed.
//
template <typename C>
auto expensive_but_lossless_popper(C & container)
-> typename std::unique_ptr<decltype(container.back())>
{
    using T = decltype(container.back());

    std::unique_ptr<T> p(new T(std::move(container.back())));
    container.pop_back();
    return p;                // noexcept-guaranteed
}

編集: @Simpleが示唆したようstd::moveに、呼び出しを追加しました。back()これは、moved-from 要素が不要になったため正当であり、多くの実際のクラスには noexcept ムーブ コンストラクターが付属しているため、これで多数のケースがカバーされます。 noexcept の動きがない「奇妙な」タイプ。

于 2013-11-01T09:00:34.737 に答える
10

設計上、C++ は、例外の安全性を確保するために、すぐに使用できるメカニズムを提供していません。

実装しようとすると、最初に要素のコピーを作成し、次にコンテナーをポップして、最後にオブジェクトを呼び出し元に返します。しかし、最後の操作のコピー コンストラクターが例外をスローするとどうなるでしょうか。オブジェクトはコンテナー内に存在せず、発信者はオブジェクトのコピーを受け取りませんでした。それを防ぎ、コンテナーの操作で強力な例外保証を提供するために、同時にポップされる要素を返す操作は直接サポートされません。

于 2013-11-01T09:03:41.977 に答える