Как ввести целые числа в пустой вектор <int>? - PullRequest
1 голос
/ 09 апреля 2020
#include <iostream>
#include <vector>

int main(void) {
    std::vector<int> ivec;
    int n = 4;
    for (std::vector<int>::iterator iter = ivec.begin(); iter != ivec.begin() + n; ++iter) {
        int x;
        std::cin >> x;
        ivec.push_back(x);
    }

    return 0;
}

Выше приведен код.

Я хочу поэкспериментировать с вводом 4 целых чисел в пустой вектор.

В результате он компилируется и запускается, но никогда не выпрыгивает из l oop что бы я ни печатал.

Я внес некоторые корректировки.

Вот код:

#include <iostream>
#include <vector>

int main(void) {
    std::vector<int> ivec;
    int n = 4;
    std::vector<int>::iterator tempiter = ivec.begin();
    for (std::vector<int>::iterator iter = tempiter; iter != tempiter + n; ++iter) {
        int x;
        std::cin >> x;
        ivec.push_back(x);
    }
    std::cout << "**********************************" << std::endl;

    for (std::vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
        std::cout << *iter << std::endl;

    return 0;
}

На этот раз все работает нормально, как и ожидалось.

Я c .begin () всегда должен оставаться прежним.

Почему это не работает в первый раз? Почему это работает во второй раз?

Я думаю, что нет большой разницы.

Ответы [ 2 ]

3 голосов
/ 09 апреля 2020

Нет гарантии, что итератор сохранит то же значение при изменении std::vector. Итератор указывает на блок внутренней памяти, в котором хранятся значения std::vector. Когда вы выбираете элемент * sh и для него нет места, весь блок перераспределяется, старые элементы копируются в новый блок, а новый элемент вставляется в конце. С этого момента начальный итератор указывает на начало нового блока и его старое значение становится недействительным. Вы не должны использовать std::vector итераторы таким образом, а использовать общее количество элементов в векторе:

for (; ivec.size() < n; )
{
    ...
}
2 голосов
/ 09 апреля 2020

Три причины:

  1. Недействительность: std::vector иногда перераспределяет себя, и когда это происходит, все итераторы становятся недействительными. Поскольку вы не знаете, когда произойдет перераспределение, следует предполагать, что итератор становится недействительным после каждой вставки.
  2. Нарушение доступа: iter + n возвращает элемент, который идет после последней, и, следовательно, может вызвать нарушение доступа при разыменовании , поэтому следует избегать.
  3. Значение l oop бесконечно, потому что ive c .begin () вычисляется снова и снова, а оригинальный итер был в памяти. Это деталь реализации, и, следовательно, это может не привести к бесконечному l oop на другой машине.

Учитывая мой ответ, ваш второй код не должен работать так же хорошо, и если он это сделает, это случайно.

Правильный способ сделать это без итераторов:

#include <iostream>
#include <vector>

int main(void) {
    std::vector<int> ivec;
    int n = 4;
    // consider writing ivec.resize(n);
    for (int i = 0; i < n; ++i) {
        int x;
        std::cin >> x;
        ivec.push_back(x);
    }

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