В чем разница между begin() и data()

#c #vector #stl

#c #вектор #stl

Вопрос:

begin() и data() оба возвращают итератор, указывающий на первый элемент. Но в определении data() говорится, что оно возвращает прямой указатель на массив памяти, используемый внутри vector для хранения принадлежащих ему элементов. Я также могу использовать их для доступа к любому элементу. Итак, чем они оба отличаются? рассмотрим следующий пример,

 #include <iostream>
#include <vector>

int main() {
    std::vector<int> v;
    v.reserve(5);

    for (int i = 1; i <= 5; i   ) v.push_back(i);
    
    auto it = v.begin();
    auto pos = v.data();

    std::cout << "First element : " << *it << std::endl;
    std::cout << "First element : " << *pos << std::endl;

    std::cout << "Third element : " << it[2] << std::endl;
    std::cout << "Third element : " << pos[2] << std::endl;
}
  

Комментарии:

1. Вы ошибаетесь. Только один из этих методов возвращает итератор. Другой нет.

2. std::vector<T>::begin по сравнению std::vector<T>::data .

3. @SamVarshavchik с определенной точки зрения, OP на самом деле не ошибочен. Указатель является допустимым итератором. Итераторы предназначены для имитации указателей. Итак, в этом смысле begin() и data() оба возвращают итераторы к первому элементу, просто разные типы итераторов.

Ответ №1:

 std::vector::begin()
  

v.begin() возвращает итератор, ссылающийся на первый элемент в векторе.

 std::vector::data()
  

v.data() возвращает указатель на первый элемент в массиве, используемый внутри вектора.

Ответ №2:

Все типы контейнеров имеют an iterator , но только некоторые типы контейнеров являются смежными и поддерживают data() . Например,

 vector<int> v;
copy(v.begin(), v.end(), ostream_iterator<int>(cout, "n"));
v.data(); // ok

list<int> l;
copy(l.begin(), l.end(), ostream_iterator<int>(cout, "n"));
l.data(); // no
  

Верно, что int* from int* vector<int>::data() удовлетворяет iterator_traits<int*>::iterator_category == random_access_iterator_tag , и это vector<int>::iterator может быть реализовано как int* . Однако стандарт этого не требует, и было бы законно реализовать vector<int>::iterator что-то вроде

 class vector<T> {
    class iterator {
        vector<T>* v;
        vector<T>::size_type pos;
    };
};
  

Следовательно, без data() этого вам пришлось прибегнуть к таким трюкам, как amp;v[0] или amp;*v.front() , чтобы получить доступ к базовой непрерывной памяти, поддерживающей a vector . Так было до появления C 11 data() .