Для C ++ Random Access Iterator (векторный итератор), как вычисляется разница между итераторами? - PullRequest
2 голосов
/ 06 января 2020

У меня есть следующий код для рандомизации элементов в итераторе произвольного доступа (vector<int>::iterator) -

#include <vector>
#include <list>
#include <iterator>
#include <algorithm>
#include <stdlib.h>
#include <iostream>
using namespace std;

template<class RandomAccesIterator>
void randomize(RandomAccesIterator iterBegin, RandomAccesIterator iterEnd)
{
    while (iterBegin != iterEnd)
    {
        int rand1 = rand();
        auto iterdiff = iterEnd - iterBegin;
        auto secondarg = iterBegin + rand1 % (iterdiff);
        iter_swap(iterBegin, secondarg);
        ++iterBegin;
    }
}

И ниже приводится функция main ():

int main()
{
    //container used as to apply algorithm to.
    list<int> List = {34,77,16,2,35,76,18,2,56};

    //randomize example.
    cout << "calling randomize on sorted vector: " << endl;
    List.sort();
    vector<int> temp(List.begin(), List.end());
    cout << "before randomize: " << endl;
    for (vector<int>::iterator it = temp.begin(); it != temp.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;

    randomize(temp.begin(),temp.end());
    cout << "after randomize: " << endl;
    for (vector<int>::iterator it = temp.begin(); it != temp.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl<<endl;
    return 0;
}

In функция шаблона рандомизации, как вычисляется разница между итераторами (iterEnd - iterBegin)?

Я попробовал пару вещей в непосредственном окне, и похоже, что iterEnd - iterBegin вычисляется так (вектор имеет 9 элементов в нем, а приведенный ниже расчет дает 9). Я попытался использовать различное количество элементов в vector<int>, и каждый раз ответ был правильным. Вычисление впервые встречается с iterEnd - iterBegin в то время как l oop (то есть для 9 элементов в векторе):

В ближайшем окне -

1.

iterEnd
{-33686019}
    [ptr]: 0x0080f9dc {-33686019}
    [Raw View]: {...}

2.

iterBegin
{2}
    [ptr]: 0x0080f9b8 {2}
    [Raw View]: {...}

3.

0x0080f9dc-0x0080f9b8 //iterEnd - iterBegin gives 36.
36

4.

36/4 //Dividing 36 by 4, since an integer is 4 bytes (we are iterating over a vector of integers).
9

Я также пробовал с 8 элементами в vector<int>, и тот же тип расчета привел к 8 элементам в шаге 4. выше.

У меня есть пара вопросов здесь:

  1. Это шаги, которые я выполняю чтобы получить правильное количество элементов в векторе (шаги с 1 по 4. выше)?
  2. На шаге 4 выше я делю 36, что в десятичном виде - на 4 байта. Как это дает мне правильный результат? Это имело бы смысл, если бы я делил 36 байтов на 4 байта, и тогда это дало бы мне 9 элементов. Почему деление десятичных 36 на 4 байта дает мне правильный ответ?

Обратите внимание: я использую следующий компилятор: Microsoft Visual Studio Enterprise 2019 (версия 16.2.1) , Платформа операционной системы представляет собой 64-разрядный процессор на базе x64. Я строю на среде Debug x86. Windows редакция Windows 10 Pro

1 Ответ

3 голосов
/ 06 января 2020

Ваши шаги верны, но только потому, что:

  • int имеет длину 4 байта на ваша система
  • std::vector<int>::iterator происходит с тривиально обернуть необработанный указатель (int*) на вашей системе

Вместо жесткого кодирования значения 4, вы можете использовать sizeof(int) для вычисления правильного количества байтов в любой системе , в которой вы компилируете свой код.

std::size_t numElements = (0x0080f9dc - 0x0080f9b8) / sizeof(int);  // Better

Что касается вашего второго вопроса, вычисляемое вами 36 не является десятичным значением без единиц измерения. Необработанное целочисленное значение необработанного указателя (помните: std::vector<int>::iterator тривиально переносит int*, поэтому он имеет одинаковый размер) использует байты в качестве неявной единицы, поэтому вы * * * * * * на самом деле делите байты на байты в вашем steps.

Наконец, я предлагаю избегать такого рода арифметических указателей c ( обоснование ). Стандарт уже предоставляет функцию для вычисления именно этого значения, std::distance, и он будет корректно работать на всех стандартных итераторах и в любой системе, на которой вы компилируете свой код.

std::size_t numElements = std::distance(iterBegin, iterEnd);  // Best
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...