Почему сигнатура функции для итератора c ++ с последовательным доступом не использует указатели? - PullRequest
0 голосов
/ 22 февраля 2019

Например, в этом фрагменте начало и конец, похоже, используются в качестве указателей.Тем не менее, в объявлении функции In * beg, In * end не предоставляется и не принимается компилятором c ++.Почему мы используем его как указатель, но не объявляем его как аргумент указателя на функцию?

#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
using namespace std;

template<class In, class X> void myreplace (In beg, In end, const X& x, const X& y)
{
    while (beg != end)
    {
        if (*beg == x) *beg = y;
        beg++;
    }
}

int main()
{
    vector<int> veca = { 1, 3, 4, 4, 1, 4, 4 };
    myreplace(veca.begin(), veca.end(), 4, 2);
    copy(veca.begin(), veca.end(), ostream_iterator<int>(cout, ","));
}

Ответы [ 4 ]

0 голосов
/ 22 февраля 2019

Ничто не мешает вам передавать указатели на myreplace.например, при вызове

int Carray[7] = { 1, 3, 4, 4, 1, 4, 4 };
myreplace(Carray, Carray + 7, 4, 2);

Параметр шаблона In определяется как int *, а X - int.Это так же, как если бы вы написали

void myreplace (int * beg, int * end, const int & x, const int & y)
{
    while (beg != end)
    {
        if (*beg == x) *beg = y;
        beg++;
    }
}

Это также принимает не указатели, которые ведут себя как указатель (например, модель InputIterator )

0 голосов
/ 22 февраля 2019

Итераторы обычно являются не просто указателями, а абстракцией указателей.

Согласно их общим требованиям :

Их семантика является обобщением большей части семантики указателей в C ++.Это гарантирует , что каждый шаблон функции, который принимает итераторы, работает также с обычными указателями .

Так что вы также можете сделать это вместо этого:

myreplace(&veca[0], &veca[6], 4, 2);

Где &veca[0] и &veca[6] являются указателями на первый и последний элементы вектора veca.

Это возможно, поскольку оператор [] возвращает ссылку на элемент в указанном месте.

0 голосов
/ 22 февраля 2019

Вы имеете в виду правильный код, как показано ниже:

template<class In, class X> void myreplace (In* beg, In* end, const X& x, const X& y)
{
    while (*beg != *end)
    {
        if (**beg == x) **beg = y;
        *beg++;
    }
}

Я думаю, во-первых, вы должны понимать базовые знания шаблонов в C ++, на самом деле в STL итератор определяется как указатель, но это не так.t означает, что тип указателя является единственным для итератора

typedef T* iterator;
0 голосов
/ 22 февраля 2019

Оператор разыменования может быть определен для любого определенного типа использования путем перегрузки унарной функции operator*.

Тип, возвращаемый veca.begin(), является таким типом.Объект такого типа можно разыменовать с помощью оператора *.

Итераторы, возвращаемые функциями-членами begin() большинства контейнеров из стандартной библиотеки, поддерживают такую ​​операцию.Следовательно, вы можете использовать:

std::vector<int> a = {10, 20, 30};
std::vector<int>::iterator iter = a.begin();
int item = *iter;

и

std::set<int> a = {10, 20, 30};
std::set<int>::iterator iter = a.begin();
int item = *iter;

и

std::map<int, double> a = {{10, 2.5}, {20, 5.8}};
std::map<int, double>::iterator iter = a.begin();
std::pair<int, double> item = *iter;
...