Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Странная проблема с использованием vector


Автор: gAlexKo 16.1.2015, 13:18
В упрощенном виде проблема такая. Я создаю вектор (vector) из четырех списков. Каждый список это поле индекса для сортировки и сам список в виде TStringList. После сортировки вектора два последних элемента пропадают, например обращение по индексу 3 вызывает ошибку выхода за пределы TStringList (List index out of bounds). Вот упрощенный код проблемы, посмотрите пожалуйста. Я компилировал это как консольное приложение CBuilder 6.

#include <stdio.h>
#include <vector>
#include <Classes.hpp>
#include <algorithm>
using namespace std;

struct SPISOK_STRUCT
{
int sorting_field;             //по этому полю будет сортировка
TStringList *spisok;

    SPISOK_STRUCT(void)  { sorting_field=0; spisok = new TStringList; }
    ~SPISOK_STRUCT(void) { delete spisok; spisok=NULL; }
    SPISOK_STRUCT(const SPISOK_STRUCT& x)
    {
      spisok = new TStringList;
      sorting_field = x.sorting_field;
      for(int i=0; i < x.spisok->Count; i++)
         spisok->Add(x.spisok->Strings[i]);
    }

    SPISOK_STRUCT& operator= (const SPISOK_STRUCT& x)
    {
      sorting_field = x.sorting_field;
        spisok->Clear();
        for(int i=0; i < x.spisok->Count; i++)
          spisok->Add(x.spisok->Strings[i]);
      return *this;
    }

   friend bool operator< (const SPISOK_STRUCT &x, const SPISOK_STRUCT &y)
   {
      bool ret = (x.sorting_field < y.sorting_field);
      return ret;
   }
};

/*---------------------------------------------*/
int main(int argc, char* argv[])
{
AnsiString astr;
vector<SPISOK_STRUCT> spiski;  //вектор списков

   spiski.clear();
   for(int i=1; i<=4; i++)  //делаем 4 списка по 2 строки в каждом
     {
     SPISOK_STRUCT x;
        for(int j=1; j < 3; j++)
         {
          AnsiString astr = AnsiString("spisok N'") + i + " line" + j;
          x.spisok->Add(astr);
         }

     x.sorting_field = i;
     spiski.insert(spiski.end(), x);
     }

     //тестовый вывод строки из 4-го списка
astr = spiski[3].spisok->Strings[0];
printf("stable_sort1: %s\n", astr.c_str());

 stable_sort(spiski.begin(), spiski.end());
     //тестовый вывод строки из 4-го списка
astr = spiski[3].spisok->Strings[0];
printf("stable_sort2: %s\n", astr.c_str());

return 0;
}
/*------------------------------------------*/

Автор: borisbn 30.1.2015, 10:08
Вроде всё работает как надо - http://ideone.com/5NdPXN
Ты уверен, что проблема не в "боевой" программе, а и в приведённом тобой упрощённом примере тоже ?

Автор: gAlexKo 30.1.2015, 13:34
Цитата(borisbn @ 30.1.2015,  10:08)
Вроде всё работает как надо - http://ideone.com/5NdPXN
Ты уверен, что проблема не в "боевой" программе, а и в приведённом тобой упрощённом примере тоже ?

Да, проверил еще раз. Возможно ты не заметил - это на самом деле не заметно в консольном режиме - программа вылетает без сообщений.  Попробуй поставить break на return. Нужно увидеть результат от
printf("stable_sort2: %s\n", astr.c_str());

Если у тебя есть CBuilder6, то вот полный консольный проект (см архив).

PS: Между прочим если заметить stable_sort на sort, то работает. 

Автор: borisbn 30.1.2015, 14:36
Проблема в том, что в операторе присваивания ты не проверяешь, что присваивают объект самому себе.
Добавь в начало SPISOK_STRUCT& operator= (const SPISOK_STRUCT& x) такие строчки 
Код
      if ( &x == this ) {
        int bp = 0;
        return *this;
      }

и поставь breakpoint на int bp = 0;.
На IdeOne этого не происходит, т.к. там другая реализация stable_sort.

Автор: gAlexKo 2.2.2015, 10:38
Цитата(borisbn @ 30.1.2015,  14:36)
Проблема в том, что в операторе присваивания ты не проверяешь, что присваивают объект самому себе.
Добавь в начало SPISOK_STRUCT& operator= (const SPISOK_STRUCT& x) такие строчки 
Код
      if ( &x == this ) {
        int bp = 0;
        return *this;
      }

и поставь breakpoint на int bp = 0;.
На IdeOne этого не происходит, т.к. там другая реализация stable_sort.

Да, действительно, спасибо! Честно говоря как-то всегда делал операторы равно без такого анализа и вроде все обходилось. Все работает, даже без " int bp = 0; smile

Автор: feodorv 2.2.2015, 18:07
Цитата(gAlexKo @  2.2.2015,  10:38 Найти цитируемый пост)
даже без " int bp = 0;

Так ведь это только для
Цитата(borisbn @  30.1.2015,  14:36 Найти цитируемый пост)
поставь breakpoint на int bp = 0;

А так это не нужно.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)