【问题标题】:Erasing last element from a set in C++从 C++ 中的集合中擦除最后一个元素
【发布时间】:2020-11-06 11:16:52
【问题描述】:
    #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() 是否指向同一个元素?

【问题讨论】:

  • s.rbegin()--s.end() refer 指向同一个元素,但它们的类型不同。这个问题不是针对set

标签: c++ c++17 c++-standard-library reverse-iterator


【解决方案1】:

std::set::rbegin 返回一个 reverse_iterator,从技术上讲它指向同一事物,但该集合没有接收 reverse_iterator 作为参数的擦除方法。

【讨论】:

  • 我不明白为什么它不起作用,最终,它们不是指向同一事物的两个指针吗?函数期望的输入是指向数组中某个元素的迭代器,不是吗?
  • @RamPrabodhInduri 它们不是指针。它们是迭代器,并且具有不同的类型。一个是函数接受的iterator,另一个是reverse_iterator,它与iterator完全不同。
  • 好的,明白了,谢谢,我假设迭代器就像指针一样。
  • 迭代器指针(在很多方面)。它们与指针相同。
  • @RamPrabodhInduri 迭代器是指针式的,在设计上,它们的接口与指针有一些相似之处。目的是如果实现者选择,一些容器可以使用指针作为迭代器。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2018-08-01
    相关资源
    最近更新 更多