Как изменить определенный элемент вектора C ++ STL - PullRequest
42 голосов
/ 12 апреля 2010
vector<int> l;
for(int i=1;i<=10;i++){
   l.push_back(i);
}

Теперь, например, как мне изменить 5th element вектора на -1?

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

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

Ответы [ 5 ]

101 голосов
/ 12 апреля 2010

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

l.at(4) = -1;

или

l[4] = -1;
10 голосов
/ 29 сентября 2015

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

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

  • Использование оператора []
  • Использование функции-члена at(...)
  • Использование итератора в сочетании с заданным смещением
  • Использование std::for_each из заголовка algorithm стандартной библиотеки C ++. Это еще один способ, который я могу порекомендовать (он использует внутренне итератор). Вы можете прочитать больше об этом, например, здесь .

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

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;

Мы получим:

прекращение вызова после выброса экземпляра 'std :: out_of_range'
what (): vector :: _ M_range_check: __n (который равен 10)> = this-> size () (что 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(...) всегда, когда это возможно, не только потому, что он более читабелен по сравнению с доступом к итератору, но и из-за проверки ошибок на недопустимый индекс, о которой я упоминал выше, как для итератора с комбинацией смещений, так и для оператора [] .

6 голосов
/ 12 апреля 2010

Это должно сделать это:

l[4] = -1
5 голосов
/ 12 апреля 2010

Вы можете использовать оператор индекс

l[4] = -1
1 голос
/ 21 марта 2018

Я предпочитаю

l.at(4)= -1;

, в то время как [4] ваш индекс

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...