Понимание .begin и .end в векторах - PullRequest
1 голос
/ 22 января 2020

Я изучаю векторы из этого поста , и они начинаются с итераторов. Они определяют .begin и .end следующим образом:

begin () - возвращает итератор, указывающий на первый элемент в векторе

end () - возвращает итератор, указывающий на теоретический элемент, который следует за последним элементом в векторе

И затем они дают следующий фрагмент кода, я добавил третий для l oop к express моего вопроса.

#include<iostream>
#include<vector>

int main() {
    std::vector <int> g1; //creating a vector
    for (int i = 1; i <= 3; i++){
        g1.push_back(i);
    }
    std::cout << "Output of beginning and end values: ";
    for (auto i = g1.begin(); i != g1.end(); i++) {
        std::cout << *i << " "; 
    }
    std::cout << "\nOutput of beginning and end addresses: ";
    for (auto i = g1.begin(); i != g1.end(); i++) {
        std::cout << &i << " ";
    }
     //"Output of beginning and end values: 1 2 3"
     //"Output of beginning and end addresses: 0105FB0C 0105FB0C 0105FB0C"
    return 0;
}

Моя путаница заключается в том, что адрес i остается прежним, но значение, которое i изменилось. Не означает ли i*, что i просто разыменовано? Таким образом, что-то должно изменить значение i, если его адрес не меняется, чтобы иметь возможность иметь другое значение. Я думаю, что я могу путать итераторы с указателями. Я знаю, что auto в основном вывод типа, но это все.

Итак, мой вопрос: как меняется значение i, если его адрес одинаков для каждого элемента в векторе?

Ответы [ 3 ]

7 голосов
/ 22 января 2020

&i - адрес локальной переменной i. Это не изменится. *i разыменовывает итератор и возвращает значение в этом элементе вектора. &*i вернет указатель на элемент в векторе.

Таким образом, вы oop должны использовать

std::cout << &*i << " ";

, чтобы увидеть изменение адресов.

1 голос
/ 22 января 2020

Для большей наглядности рассмотрим похожий код, но вместо вектора используется массив.

#include <iostream>
#include <iterator>

int main() 
{
    int a[] = { 1, 2, 3 };

    for ( auto p = std::begin( a ); p != std::end( a ); p++ )
    {
        std::cout << "The address of p is " << &p
                  << ", its value is " << p
                  << ", and the pointed value is " << *p
                  << '\n';
    }

    return 0;
}

Вывод программы может выглядеть как

The address of p is 0x7ffcaf6a6830, its value is 0x7ffcaf6a683c, and the pointed value is 1
The address of p is 0x7ffcaf6a6830, its value is 0x7ffcaf6a6840, and the pointed value is 2
The address of p is 0x7ffcaf6a6830, its value is 0x7ffcaf6a6844, and the pointed value is 3

Эта часть выводимые строки

The address of p is 0x7ffcaf6a6830

не изменяются, поскольку это адрес самой локальной переменной (указателя) p.

Эта часть строк

its value is 0x7ffcaf6a683c

изменяется, потому что в пределах l oop значение указателя изменяется

for ( auto p = std::begin( a ); p != std::end( a ); p++ )
                                                        ^^^^

На каждой итерации указатель указывает на следующий элемент массива.

Эта часть строки

and the pointed value is 1

также изменяются, поскольку выводится указанное значение из-за разыменования указателя.

То же самое происходит с итератором вектора.

1 голос
/ 22 января 2020

Я думаю, что я могу путать итераторы с указателями

Ну, указатели являются итераторами, так что это понятно. Но не все итераторы являются указателями. Другими словами, не указатели также могут быть итераторами.

Я знаю, что auto - это в основном вывод типов, но это все.

В этом случае тип выводится как std::vector<int>::iterator, потому что это тип, который возвращает std::vector<int>::begin.

Итак, мой вопрос, как изменить значение i, если его адрес одинаков для каждого элемента вектора?

Значение i изменяется на i++ в l oop. Адрес, где хранится объект, никогда не меняется в течение всего времени существования объекта. Независимо от того, является ли тип этого объекта указателем, каким-то другим итератором или не итератором вообще.

...