2010-04-12 3 views
35
vector<int> l; 
for(int i=1;i<=10;i++){ 
    l.push_back(i); 
} 

Сейчас, к примеру, как изменить 5th element вектора к -1?Как изменить конкретный элемент STL вектора C++

Я пробовал l.assign(4, -1); Он не ведет себя так, как ожидалось. Ни один из других векторных методов не подходит.

Я использовал вектор, поскольку мне нужен случайный доступ в моем коде (используя l.at(i)).

+8

Все, что случилось с л [4] = -1; Или l.at (4) = -1, если хотите. – 2010-04-12 18:07:27

ответ

85

at и operator[] возвращают ссылку на индексированный элемент, так что вы можете просто использовать:

l.at(4) = -1; 

или

l[4] = -1; 
+9

И вам лучше использовать привычку 'at', менее идиоматично, но проверка границ бесценна. –

+2

@Matt: Ошибки, связанные с ошибками, как правило, являются ошибкой программиста, а 'at' выдает исключение. То есть, 'assert' будет лучше, и я думаю, что и MSVC, и gcc проверили итераторы. – GManNickG

+0

@GMan Лично я более или менее прекратил использовать утверждения. Я обычно использую at() в ситуациях, когда я могу сделать ошибку кодирования (например, я бы не использовал его в цикле for-loop) - то, что я так же могу сделать, когда пишу утверждение. – 2010-04-12 18:56:45

6

Это следует сделать это:

l[4] = -1 
5

Вы можете использовать subscript operator

l[4] = -1 
+1

Привет, Том, вы можете рассказать, как добиться этого для двумерных векторов, например «вектор > VC» или «vector VC (100,100)». –

7

Даже если @JamesMcNellis ответ является допустимым я хотел бы объяснить, что-то об обработке ошибок, а также тот факт, что есть еще один способ сделать то, что вы хотите.

У вас есть три способа доступа конкретного элемента в векторе:

  • Использование [] оператора
  • Использование функции члена at(...)
  • Использование итератора в сочетании с заданным офсетных

В следующих примерах я буду использовать следующий вектор в качестве лабораторной крысы:

static const int arr[] = {1, 2, 3, 4}; 
std::vector<int> v(arr, arr+sizeof(arr)/sizeof(arr[0])); 

Это создает вектор, как показано ниже:

1 2 3 4 

Сначала давайте посмотрим на [] способ делать вещи. Он работает практически так же, как вы ожидаете при работе с обычным массивом. Вы указываете индекс и , возможно, получаете доступ к интересующему вас товару. Я говорю , возможно,, потому что оператор [] не проверяет, действительно ли вектор имеет много элементов. Это приводит к бесшумному недопустимому доступу к памяти. Пример:

v[10] = 9; 

Это может привести или не может привести к мгновенному сбою. Худший случай, конечно, если это не так, и вы действительно получаете то, что кажется действительным. Подобно массивам, это может привести к расходованию времени, пытаясь найти причину, по которой, например, 1000 строк кода, вы получите значение 100 вместо 234, которое несколько связано с тем самым местом, где вы извлекаете элемент из вашего вектора.

Лучше всего использовать at(...). Это автоматически проверит поведение out of bounds и сломает std::out_of_range. Таким образом, в случае, когда мы имеем

v.at(10) = 9; 

Мы получим:

Terminate вызывается после метания экземпляра 'станд :: out_of_range'
, что(): вектор :: _ M_range_check: __n (который 10)> = this-> размер() (который 4)

Третий способ похож на [] оператора в том смысле, можно ввернуть вещи. Вектор, подобный массиву, представляет собой последовательность блоков непрерывной памяти, содержащих данные того же типа. Это означает, что вы можете использовать свой начальный адрес, назначив его итератору, а затем просто добавьте смещение к этому итератору. Смещение просто означает, сколько элементов после первого элемента, который вы хотите пройти:

std::vector<int>::iterator it = v.begin(); // First element of your vector 
*(it+0) = 9; // offest = 0 basically means accessing v.begin() 
// Now we have 9 2 3 4 instead of 1 2 3 4 
*(it+1) = -1; // offset = 1 means first item of v plus an additional one 
// Now we have 9 -1 3 4 instead of 9 2 3 4 
// ... 

Как вы можете видеть, мы можем также сделать

*(it+10) = 9; 

, который снова неверный доступ к памяти. Это в основном то же самое, что и использование at(0 + offset), но без проверки ошибок за пределами.

Я бы советовал использовать at(...) по возможности не только потому, что он более читабельен по сравнению с доступом итератора, а из-за ошибки проверки неверного индекса, который я упомянул выше как для итератора со смещенной комбинацией, так и для оператора [].


EDIT: Я забыл о std::for_each от algorithm заголовка стандартной библиотеки C++. Это еще один способ, который я могу рекомендовать (он использует внутренне итератор). Вы можете узнать больше об этом, например, here.

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