从 C++ 中的集合中删除最后一个元素

Erasing last element from a set in C++

    #include <bits/stdc++.h>
    #define FIN ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    #define SZ(s) int(s.size())
    using namespace std;
    typedef long long ll;
    int main()
    {
        FIN;
        set<ll>s;
        ll N, M;
        cin >> N >> M;
        ll x;
        for(ll i = 0; i < N+M; i++)
        {
            cin >> x;
            if(x==-1)
            {
                auto x = *s.rbegin();
                cout<<x<<'\n';
//-------------------------------------------------------------------------------------------------
                s.erase( --s.end() ); // --s.end() when replaced with s.rbegin(), gives an error
//------------------------------------------------------------------------------------------------
            }
            else
            {
                s.insert( x );
            }
        }
        
    }

在水平线之间的代码中,我试图从集合中删除最后一个元素。

当我写 s.erase( s.rbegin( ) ) 而不是 s.erase( --s.end( ) ) ,它给了我一个编译错误说:

 **error: no matching function for call to ‘std::set<long long int>::erase(std::set<long long int>::reverse_iterator)’
   20 |    s.erase( s.rbegin() );**

不是 s.rbegin() 和 --s.end() 指向同一个元素?

std::set::rbegin returns a reverse_iterator,技术上指向同一件事,但集合没有接收 reverse_iterator 作为参数的擦除方法。

reverse_iterator 的实现方式与 iterator 不同。 iterator 的逻辑地址和物理地址相同,但 reverse_iterator 的逻辑地址和物理地址不同。例如:s.end()s.rbegin() 具有相同的物理地址但是 *s.end() 会给你一个错误但是 *s.rbegin() 会给你容器的最后一个值 s .

下面的代码会让事情变得清晰:

#include <iostream>
#include <set>

using namespace std;

int main()
{
    set<int> S{ 1, 2, 3 };
    
    set<int>::iterator itr = S.find(2);
    cout << *itr << endl;

    set<int>::reverse_iterator r_itr(itr);
    cout << *r_itr << endl;

    cout << itr._Ptr << ' ' << r_itr.base()._Ptr << endl;

    //S.erase(r_itr);       // ERROR!
    S.erase(r_itr.base());

    for (int e : S)
        cout << e << ' ';
}

在我的机器上,它产生了以下输出:

2
1
00F85DA8 00F85DA8
1 3