【问题标题】:No matching member function for call to 'erase' while erasing a value from vector从向量中擦除值时没有匹配的成员函数调用“擦除”
【发布时间】:2020-11-18 22:18:22
【问题描述】:

我正在尝试编写此代码,但这给出了错误

No matching member function for call to 'erase'clang(ovl_no_viable_member_function_in_call)
stl_vector.h(1317, 7): Candidate function not viable: no known conversion from 'int' to 'std::vector<int, std::allocator<int> >::const_iterator' (aka '__normal_iterator<const int *, std::vector<int, std::allocator<int> > >') for 1st argument
stl_vector.h(1344, 7): Candidate function not viable: requires 2 arguments, but 1 was provided

这是我的代码

#include <iostream>
#include <vector>

using namespace std;


int sockMerchant(int n, vector<int> ar) {
    int pairCount=0;
    for(int i=0;i<ar.size();i++)
    {
        for(int j=i+1;j<ar.size();j++)
        {
            if(ar[i]==ar[j])
            pairCount++;
            ar.erase(j);
        }
    }
    return pairCount;
}

int main()
{
    int n;
    cin>>n;
    vector <int> arr;
    for(int i=0;i<n;i++)
    {
        int e=0;
        cin>>e;
        arr.push_back(e);
    }
    sockMerchant(n, arr);
}

如果可以的话,请告诉我为什么会出现这个错误,因为我采用了与 gfg 中相同的擦除功能方法。

【问题讨论】:

  • 使用标准函数时出现的类似错误表明您应该查阅您最喜欢的有关您尝试调用的函数的文档(在这种情况下为erase)。
  • 所以没有办法或解决方法像我一样擦除元素?
  • Vector 不允许按索引擦除元素。为此,需要使用迭代器 - 但要小心,因为迭代器在 erase() 调用后变得无效。根据您要实现的具体目标,可能已经有 STL 算法可以做到这一点。如果你描述它是什么,有人可能会提供帮助。
  • 你不能通过索引擦除元素,只能通过迭代器。不过要小心擦除循环中的元素。 erase() 使迭代器无效,并递减 size()。 StackOverflow 上有很多与此主题相关的问题,例如C++ nested for loop with erasing elementsRemove elements of a vector inside the loopErase in a loop with a condition in C++
  • 我很难弄清楚sockMerchant() 的真正意图是什么。它充满了逻辑问题,在不知道实际目标的情况下很难纠正。

标签: c++ vector compiler-errors


【解决方案1】:

std::vector::erase() 不将索引作为输入。这就是编译器所抱怨的。 erase() 取而代之的是 iterator,例如:

ar.erase(ar.begin()+j);

请注意,您必须小心,因为erase() 将使迭代器和对元素的引用在被擦除元素处/之后失效。但更重要的是,它还会递减向量的size(),您在内部循环中没有正确考虑到这一点,因此它会跳过元素。

就此而言,您的外部循环非常无用。它最多只会迭代 1 次,因为内部循环会删除第一个元素之后的 所有 元素。那是你真正想要的吗?如果您的目的只是计算元素,则根本不需要删除它们。

此外,您正在传递vector 按值,这将生成vector副本。您对副本所做的任何修改都不会反映给调用者。如果要修改调用者原来的vector,则需要通过非常量引用来代替。

更新:鉴于您所说的有关您的预期目标,请尝试更多类似的方法:

int sockMerchant(vector<int> ar) {
    int pairCount = 0;
    for(size_t i = 0; i < ar.size(); ++i) {
        for(size_t j = i + 1; j < ar.size(); ++j) {
            if (ar[i] == ar[j]) {
                ++pairCount;
                ar.erase(ar.begin()+j);
                break;
            }
        }
    }
    return pairCount;
} 
...
sockMerchant(arr);

或者,另一种选择是先对数组进行排序,然后使用 1 个循环来计算 now-adjacent 对,而不删除任何元素,例如:

#include <algorithm>

int sockMerchant(vector<int> ar) {
    sort(ar.begin(), ar.end());
    int pairCount = 0;
    for(size_t i = 1; i < ar.size(); ++i) {
        if (ar[i-1] == ar[i]) {
            ++pairCount;
            ++i;
        }
    }
    return pairCount;
}

【讨论】:

  • 我想计算数组中的对数。因此,为了避免将三个元素计为 2 对,我想从数组中删除该元素,使其无法再次计数。
  • @DjAgor "我想计算数组中的对数" - 但这并不是您的代码实际在做的事情。它采用第一个元素,计算该元素在整个数组中重复的次数,并擦除第一个元素之后的所有元素。至少,您的代码在if(ar[i]==ar[j]) 块中缺少{} 括号和break。我建议改为std::sort()'ing 数组,然后用 1 个循环计算相邻对而不擦除任何元素。
  • 是的,我正要包括编辑。你的方法对我来说听起来更好。它只是使用擦除点击了我,所以我使用了它。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多