2014-04-11 3 views
0

Я пытаюсь выполнить итерацию по вектору и удалить из него определенные элементы. Я работаю над концом вектора вниз, так что я не испортил итератор, поскольку элементы удалены, но когда я пытаюсь скомпилировать его, вы бросаете ошибку. Я просмотрел некоторые другие сообщения с этой же ошибкой, но не видел ничего, что применимо к моей ситуации, или если бы я этого не понимал, я все еще довольно новичок в C++ и программировании вообще. Ниже приведен пример более простого кода для иллюстрации моей проблемы.vector .erase error c2664

#include <iostream> 
#include <vector> 

using namespace std; 

int vectorErase(vector<int>, int &); 

int main() 
{ 
    vector<int> test; 

    for(int i=0; i<11;i++) 
    { 
     test.push_back(i); 
     cout<<test[i]; 
    } 

    for(int i=10;i<=0;i--) 
    { 
     vectorErase(test, i); 
     cout<<test[i]; 
    } 

    system("pause"); 
    return 0; 
} 

int vectorErase(vector<int> test, int &iterat) 
{ 
    if(test[iterat]>6) 
    { 
     test.erase(iterat); 
    } 
    return 0; 
} 

любая помощь будет большим

+3

Какая ошибка? – ChronoTrigger

+0

опубликуйте сообщение об ошибке и укажите строку кода с ошибкой. – atoMerz

+1

Так много чего не так ... Для одного, 'int &' не является [итератором] (http://en.cppreference.com/w/cpp/concept/Iterator) (это то, что 'erase()' принимает как аргумент)! – jrok

ответ

2

Наиболее насущные проблемы в вашем коде являются :

  • Передача вашего вектора значение, поэтому оригинал никогда не изменяется.
  • Не используется erase() должным образом. Он возвращает итератор в следующий элемент в последовательности, которую вы сделали не удалить (пока). Это означает, что если вы используете итераторы и удаляете элемент, вам не нужно (и не должно) увеличивать итератор. Пример следующий.
  • В сочетании с вышесказанным просто вы не используете итераторы, и вы должны быть.

Ваш код может обойтись без функции и просто сделать это:

#include <iostream> 
#include <vector> 
using namespace std; 

int main() 
{ 
    vector<int> test; 

    for(int i=0; i<11;i++) 
    { 
     cout << i << ' '; 
     test.push_back(i); 
    } 
    cout << '\n'; 

    for(auto it = test.begin(); it != test.end();) 
    { 
     if (*it > 6) 
      it = test.erase(it); 
     else 
     { 
      cout << *it << ' '; 
      ++it; 
     } 
    } 
    cout << '\n'; 

    return 0; 
} 

Выход

0 1 2 3 4 5 6 7 8 9 10 
0 1 2 3 4 5 6 

Я настоятельно советую вам провести несколько дней работы с итераторы. Начните с чего-то простого (как этот пример).

0

вы передаете копию вектора vectorErase, поэтому любые изменения, которые она делает его копии не имеют никакого влияния на оригинал.

Если вы хотите изменить вектор, переданный функции, вам нужно взять ссылку на оригинал, а не на копию. Это легко - вместо vector<int> test, напишите vector<int> & test.

(Вы передаете iterat ссылки, которые вам не нужны. Вы просто поставить & в неправильном месте?)

+1

И это не так, как работает 'erase'. –

1

Я пытаюсь перебирать вектор и удалить отдельные элементы из Это. Я работаю в конце вектора вниз, чтобы я не испортил итератор, поскольку элементы удалены,

В дополнение к передаче по ссылке вместо значения, вместо того, чтобы писать циклы и беспокоиться о недействительными итераторами, научиться использовать алгоритмы, а точнее, идиому erase/remove_if для контейнеров, таких как вектор. Очень просто даже для хороших программистов на C++ сделать ошибку, поэтому алгоритмы должны использоваться.

Вот пример использования идиомы (erase/remove_if).

#include <algorithm> 
//... 
bool IsGreater(int val) { return val > 6; } 
//... 
test.erase(std::remove_if(test.begin(), test.end(), IsGreater), test.end()); 

Remove_if принимает элементы, которые удовлетворяют условию и перемещают их до конца вектора. Возвращаемое значение remove_if() - это итератор, который указывает на начало перемещенных элементов. Затем erase() берет элементы и удаляет их из вектора.

Преимущество в том, что это так, много, но один из них заключается в том, что вам больше не нужно беспокоиться о «запутывании итераторов». Это очень сложно испортить - один способ испортить - либо вы предоставляете неправильные типы итераторов (тогда вы получите синтаксическую ошибку), либо ваша функция сравнения не работает (легко фиксируется). Но во время выполнения вряд ли удастся использовать недействительные итераторы.

Другим преимуществом является то, что любой хороший программист на C++ может сразу понять, что делает erase/remove_if(). Если я смотрю на ваш код, и вы никогда не говорили нам, что он сделал, я бы

1) должен прочитать его несколько раз, чтобы получить то, что происходит и

2) должен запустить его под отладчиком посмотрите, делает ли он то, что я думаю, и делаю это правильно.

С помощью алгоритмов я точно знаю, что делает код, а что еще более важно, код работает без необходимости запускать его под отладчиком.

Обратите внимание, что в примере, который я предоставил, используется простая функция IsGreater().Другие способы записи тестовой функции - использовать std :: greater <> (вместе с std :: bind1st), используя объект функции, используя лямбду и т. Д. Но я предоставил, вероятно, самый простой способ изначально понять, что такое происходит.

+0

Благодарим вас за советы по алгоритмам, я просмотрю их, но до сих пор я не использовал их и не подвергался воздействию. – James

+0

@James - я отредактировал свой ответ, чтобы добавить, что хорошие программисты на С ++ могут легко справиться с этим, даже для вещей, которые кажутся простыми, как стирание предметов из контейнера. Вот почему используются алгоритмы. – PaulMcKenzie

+0

Звуковой совет в этом ответе. Если бы я мог отказаться от своего выбранного статуса и поместить его сюда, я бы это сделал. Uptick - лучшее, что я могу предложить. – WhozCraig

0

Есть несколько проблем. Во-первых, есть факт, что вы должны передать вектор по ссылке, чтобы повлиять на оригинал.

int vectorErase(vector<int>&, int); 

Тогда есть проблема второго цикла:

for(int i=10;i>=0;i--) 
    { 
     vectorErase(test, i); 
     cout<<test[i] << ' '; 
    } 

И, наконец, функция сама с надлежащим использованием erase:

int vectorErase(vector<int> &test, int iterat) 
{ 
    if(test[iterat]>6) 
    { 
     test.erase(test.begin()+iterat); 
    } 
    return 0; 
} 
+0

Благодарим вас за разъяснение, что нужно изменить и почему, я сделал изменения, которые вы сказали, но теперь я получил следующее сообщение об ошибке. _Error ошибка C3867: 'std :: vector <_Ty> :: begin': вызов функции отсутствует список аргументов; use '& std :: vector <_Ty> :: begin', чтобы создать указатель на member_ Я бы опубликовал код, но не могу его правильно форматировать в комментарии. – James

Смежные вопросы