c ++ странное поведение массива итераторов

0

Поэтому, чтобы узнать, спросил ли кто-нибудь об этом, я вижу много вопросов об итерации массивов. Но у меня есть массив итераторов. По существу здесь, что я делаю:

У меня есть отсортированный std :: list пользовательского объекта. Объект просто содержит int и double и имеет методы для тех видов, которые вы ожидаете (конструкторы, сеттеры, геттеры, оператор <, чтобы сделать его отсортированным с помощью метода double, toSting()). Это все работает, включая сортировку.

Теперь я хочу, чтобы куча итераторов указывала на список в разных точках. Там будет один к списку списка, один к хвосту и несколько, указывающий на разные точки посередине. Я делаю это с использованием массива старого стиля (это может быть проблема - я попробую его с помощью std :: array, но я все еще хочу понять, почему это не сработало). Итак, у меня есть подпрограмма, которая инициализирует этот массив. Это почти работает. Я могу построить массив и выводить из подпрограммы, и все выглядит хорошо. Вывод извне подпрограммы последний элемент массива изменился и больше не отображается в списке. Здесь соответствующий код:

using namespace std;

#include <iostream>
#include <list>
#include <cmath>
#include <algorithm>
#include "random.h"
#include "Double_list_struct.h"

/**********************************Subroutine declarations***************************/

template <typename Tplt>
void output_list(list<Tplt> to_out);
template <typename Tplt>
void initialize_list(list<Tplt> &alist, int size);
template <typename Tplt>
void initialize_iter_array(typename list<Tplt>::iterator* itar, int size, list<Tplt> alist);

/***************************************Main routine*******************************/

int main(void)
{
  int list_size = 16;

  // Make the list that will be tested.
  list<Double_list_struct> list_to_play_with;

  initialize_list(list_to_play_with, list_size);

  list_to_play_with.sort();
  cout << "Sorted list is: " << endl;
  output_list(list_to_play_with);

  // Make an array of list<Double_list_struct>::iterator of size floor(sqrt(N))
  int iter_array_size = floor(sqrt(list_size));

  list<Double_list_struct>::iterator* iter_array;
  iter_array = new list<Double_list_struct>::iterator[iter_array_size];

  // Initialize the iterators in iter_array to point to roughly evenly spaced locations in the list

  initialize_iter_array(iter_array, iter_array_size, list_to_play_with);

  for (int i = 0; i < iter_array_size; i++)
    {
      cout << "In main routine, iter_array[" << i << "]:" << (*(iter_array[i])).toString() << endl;
    }

  cout << "Reset it, and redo the output loop??" << endl;
  iter_array[iter_array_size-1] = list_to_play_with.end();
  iter_array[iter_array_size-1]--;

  for (int i = 0; i < iter_array_size; i++)
    {
      cout << "In main routine, iter_array[" << i << "]:" << (*(iter_array[i])).toString() << endl;
    }    
}


/************************************************Subroutine code**************************************/

// Output all elements of a list to cout.

template <typename Tplt>
void output_list(list<Tplt> to_out)
{
...not important here
}


template <typename Tplt>
void initialize_list(list<Tplt> &alist, int size)
{
...not important here
}


template <typename Tplt>
void initialize_iter_array(typename list<Tplt>::iterator* itar, int size, list<Tplt> alist)
{
  itar[0] = alist.begin();
  itar[size-1] = alist.end();
  itar[size-1]--; // Recall that .end() makes an iterator point *past* the end...

  // Find out how big the list is
  int listsize = 0;
  for (typename list<Tplt>::iterator it = itar[0]; it != itar[size-1]; it++)
    {
      listsize = listsize + 1;
    }

  int spacing = floor(listsize/(size-1));

  cout << "In initialize_iter_array(): created itar[0]: " << (*itar[0]).toString() << endl;

  for (int i = 1; i < size-1 ; i++)
    {
      itar[i] = itar[i-1];

      for (int j = 0; j < spacing; j++)
    {
      itar[i]++;
    }
      cout << "In initialize_iter_array(): created itar[" << i << "]: " << (*itar[i]).toString() << endl;
    }

  cout << "In initialize_iter_array(): created itar[" << size-1 << "]: " << (*itar[size-1]).toString() << endl;
}

Это генерирует вывод

Sorted list is: 
struct[15] = 0.135837
struct[1] = 0.200995
struct[12] = 0.217693
...SNIP...
struct[8] = 0.863816
struct[14] = 0.887851
struct[2] = 0.893622
struct[10] = 0.925875
In initialize_iter_array(): created itar[0]: struct[15] = 0.135837
In initialize_iter_array(): created itar[1]: struct[5] = 0.314127
In initialize_iter_array(): created itar[2]: struct[11] = 0.704419
In initialize_iter_array(): created itar[3]: struct[10] = 0.925875
In main routine, iter_array[0]:struct[15] = 0.135837
In main routine, iter_array[1]:struct[5] = 0.314127
In main routine, iter_array[2]:struct[11] = 0.704419
In main routine, iter_array[3]:struct[-1] = 6.21551e-71
Reset it, and redo the output loop??
In main routine, iter_array[0]:struct[15] = 0.135837
In main routine, iter_array[1]:struct[5] = 0.314127
In main routine, iter_array[2]:struct[11] = 0.704419
In main routine, iter_array[3]:struct[10] = 0.925875

Итак, вы видите, что iter_array[3] верен внутри подпрограммы инициализации, но "движется" после выхода подпрограммы. Затем я перезагружаю его из подпрограммы, но, очевидно, мне не нужно этого делать...

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

  • 1
    Как правило, вы не хотите хранить итераторы для последующего использования. Существует вероятность того, что операции могут сделать их недействительными, и вы попытаетесь разыменовать элементы, которые больше не существуют.
  • 0
    Спасибо! То, что я пытаюсь создать, даст мне постоянные «указатели» в связанном списке для ускорения поиска. Так что это по крайней мере концептуально похоже на хеш-таблицу (о которой я сейчас нахожусь в процессе изучения). В старые времена, когда я изучал этот материал, мы просто использовали указатели для этого. Но очевидно, что указатели на эти дни не одобряются, поскольку они небезопасны. Поэтому я подумал сделать это с помощью итераторов. Какой тип объекта будет предлагаться для постоянных ссылок в середине списка?
Показать ещё 7 комментариев
Теги:
arrays
iterator

1 ответ

2
Лучший ответ

initialize_iter_array берет список по значению, что означает, что он ставит итераторы, указывающие на экземпляр параметра списка, а не на исходный список. Вы, вероятно, хотели бы передать список по const& вместо этого.

  • 0
    Ха ха! Да, передача по значению, а не по ссылке - это как раз проблема. 'Inititialize_iter_array (..., list <Tplt> * alist)' работает отлично.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню