Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Mesteriis
372 / 155 / 40
Регистрация: 08.08.2015
Сообщений: 1,104
Завершенные тесты: 1
#1

Интересная особенность в работе вектора - C++

10.11.2015, 00:42. Просмотров 437. Ответов 22
Метки нет (Все метки)

Доброе время суток!

PS Даже не знаю как вам объяснить не грузя кучей кода, пока попробую на словах но если нужно могу выкинуть весь код!

Значит так:
Заполняем вектор элементами (имена файлов прочитанные из директории) Вектор имеет структуру:
Имя файла (строка)
Расширение (строка)
Путь (строка)
Номер (Инт)
Дальше циклом читаем этот вектор с условием что если тип расширение равен (например) dmg (маковский exe) то скопировать его в другой вектор! а элемент в первоначальном удалить!

Но по какой то неведомой причине условия пропускает несколько элементов которые она должна отработать!
Не могу найти причину такого поведения, у кого какие мысли?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.11.2015, 00:42     Интересная особенность в работе вектора
Посмотрите здесь:

C++ интересная головоломка
Интересная сортировка C++
C++ Интересная сортировка
C++ Интересная головоломка
C++ Интересная задачка
Интересная задачка(оптимизация) C++
Интересная штука C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 00:53     Интересная особенность в работе вектора #2
Mesteriis,
по какой то неведомой причине
а я назову эту причину: ошибка в коде. причем не в коде вектора.
Mesteriis
372 / 155 / 40
Регистрация: 08.08.2015
Сообщений: 1,104
Завершенные тесты: 1
10.11.2015, 00:55  [ТС]     Интересная особенность в работе вектора #3
pproger, ОК, видишь ошибку?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
vector<MyFilesCopy> DMac;
    for (unsigned int i =0; i<v.size(); ++i)
    {
        if (checkMacFileType(v[i].Type)==true)
        {
            mfc.Number++;
            mfc.NameFiles=v[i].NameFiles;
            mfc.Type=v[i].Type;
            mfc.status=false;
            mfc.Path=v[i].Comment+"/"+v[i].NameFiles+"."+v[i].Type;
            DMac.push_back(mfc);
            v.erase(v.begin()+i);
        }
    }
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 00:55     Интересная особенность в работе вектора #4
Цитата Сообщение от Mesteriis Посмотреть сообщение
dmg (маковский exe)
с каких пор dmg это аналог exe? аналог exe в маке (да и вообще в unix) - elf! dmg - образ, обычный iso с доп заголовком.
Mesteriis
372 / 155 / 40
Регистрация: 08.08.2015
Сообщений: 1,104
Завершенные тесты: 1
10.11.2015, 00:57  [ТС]     Интересная особенность в работе вектора #5
Тут он пропускает 3 элемента

Добавлено через 1 минуту
pproger, я упростил, для многих в этой ветки и float от double не чем не отличаются!
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 01:04     Интересная особенность в работе вектора #6
Mesteriis, конечно вижу. неправильно удаляешь элементы из вектора, попутно его обходя.
Mesteriis
372 / 155 / 40
Регистрация: 08.08.2015
Сообщений: 1,104
Завершенные тесты: 1
10.11.2015, 01:06  [ТС]     Интересная особенность в работе вектора #7
pproger, Ммммм, ок, а как надо, если не трудно
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 01:08     Интересная особенность в работе вектора #8
Mesteriis, ты сначала приведи минимальный компилируемый код, который демонстрирует проблему. на простых данных.
Mesteriis
372 / 155 / 40
Регистрация: 08.08.2015
Сообщений: 1,104
Завершенные тесты: 1
10.11.2015, 01:14  [ТС]     Интересная особенность в работе вектора #9
pproger, хм, минимально компилируемый, ну ок
файл main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <iostream>
#include <stdio.h>
#include <string>
#include <iterator>
#include <vector>
#include <fstream>
#include <unistd.h>
 
#include <func.cpp>
 
 
 
using namespace std;
 
/*  Расширения для хранения
 *  Distrib Mac :   dmg, pkg
 *  Distrib Win :   exe, bat, cmd
 *  Media       :   avi, mkv, mov, mp3, ipg
 *  Sundry      :   rar, zip, ect...
*/
 
void PRINT() // для удобства не обращять внимания
{
    cout << "Печатаем вектор\n";
    for (unsigned int i=0; i<v.size(); ++i)
    {
        cout <<"# "<< i<< "  "<<v[i].number<< "\t Name "<<v[i].NameFiles<<" Type "<< v[i].Type <<endl;
    }
}
 
char Vibor;
//const char FTarget2[27]="/Users/mesteriis/Downloads";
const char Target[36]="/Users/mesteriis/Downloads/uTorrent";
 
 
int main()
{
 
    LoadExclusion();
    v.clear();
    GetDIR(Target);
    unsigned int SumMF=v.size();
    cout << "Размер очереди на копирование = " <<v.size()<< " объектов" << endl;
    cout << "Печатаем: \n";
    for (unsigned int i=0; i<v.size(); ++i)
        {
            cout <<"# "<<v[i].number<< "\t Name "<<v[i].NameFiles<<" Type "<< v[i].Type <<endl;
        }
    cout << "Для продолжения нажмите ENTER\n";
    if (cin.get()=='n') return 0;
    system ("clear");
    cout << "OK! Следуетли включить вывод в файл! И не выводить на экран?  (Да (Y) Нет (N))\n ";
    char view='\0';
    if (cin.get()!='n') view='y'; else view='n';
 
    //Distrib Mac
    vector<MyFilesCopy> DMac;
    for (unsigned int i =0; i<v.size(); ++i)
    {
        if (checkMacFileType(v[i].Type)==true)
        {
            mfc.Number++;
            mfc.NameFiles=v[i].NameFiles;
            mfc.Type=v[i].Type;
            mfc.status=false;
            mfc.Path=v[i].Comment+"/"+v[i].NameFiles+"."+v[i].Type;
            DMac.push_back(mfc);
            v.erase(v.begin()+i);
        }
    }
    if (view=='y')
    {
        cout << "Печатаем DMAC:  Размер вектора = "<<DMac.size()<< " объектов" << endl; ;
        cout <<"# "<<"\t"<<"Name"<<endl;
        for (unsigned int i=0; i<DMac.size(); ++i)
        {
            cout <<"# "<<DMac[i].Number<< "\t"<<DMac[i].NameFiles<<"."<< DMac[i].Type << endl;
        }
    }
    else
    {
        cout << "Размер очереди на копирование DMac   = "   <<DMac.size()<< " объектов" << endl;
    }
    cout << endl;
    auto ss=checkMacFileType(v[14].Type); // проверял
    cout << ss << "  "<< v[14].Type << endl; //проверял
 
    cin.get();
    //Distrib Win
    mfc.Number=0;
    vector<MyFilesCopy> DWin;
    for (unsigned int i =0; i<v.size(); ++i)
    {
        if (checkWinFileType(v[i].Type)==1)
        {
            mfc.Number++;
            mfc.NameFiles=v[i].NameFiles;
            mfc.Type=v[i].Type;
            mfc.status=false;
            mfc.Path=v[i].Comment+"/"+v[i].NameFiles+"."+v[i].Type;
            DWin.push_back(mfc);
            v.erase(v.begin()+i);
        }
    }
    if (view=='y')
    {
        cout << "Печатаем DWIN:  Размер вектора = "<<DWin.size()<< " объектов" << endl;;
            for (unsigned int i=0; i<DWin.size(); ++i)
                {
                    cout <<"# "<<DWin[i].Number<< "\t Name "<<DWin[i].NameFiles<<" Type "<< DWin[i].Type << endl;
                }
    }
    else
    {
        cout << "Размер очереди на копирование DWin   = "   <<DWin.size()<< " объектов" << endl;
    }
 
    //Media
    cout << endl;
    mfc.Number=0;
    vector<MyFilesCopy> Media;
    for (unsigned int i =0; i<v.size(); ++i)
    {
        if (checkMediaFileType(v[i].Type)==1)
        {
            mfc.Number++;
            mfc.NameFiles=v[i].NameFiles;
            mfc.Type=v[i].Type;
            mfc.status=false;
            mfc.Path=v[i].Comment+"/"+v[i].NameFiles+"."+v[i].Type;
            Media.push_back(mfc);
            v.erase(v.begin()+i);
        }
    }
    if (view=='y')
    {
        cout << "Печатаем Media:  Размер вектора ="<<Media.size()<< " объектов" << endl;;
            for (unsigned int i=0; i<Media.size(); ++i)
                {
                    cout <<"# "<<Media[i].Number<< "\t Name "<<Media[i].NameFiles<<" Type "<< Media[i].Type << endl;
                }
    }
    else
    {
        cout << "Размер очереди на копирование DWin   = "<<Media.size()<< " объектов" << endl;
    }
    cout << "test";
    //Sundry
 
    cout << endl;
    cout << "Смотрим и проверяем? для продолжения нажмите ENTER!\n";
    cin.get();
    system("clear");
    if (v.size()!=0) cout << "Осталось разобрать непонятки! Только ручками только хард-кор!\n";
    cout << "Их всего " << v.size() << endl;
    mfc.Number=0;
    vector<MyFilesCopy>Sundry;
    cout << "Дистрибутив Маc OS X (m), Windows (w). Мультимедиа файл (p). Разное (s).\n";
 
    PRINT(); //!
    int xx;
    do
    {
        for (unsigned int i=0; i<v.size(); ++i)
        {
            mfc.Number=10000;
            mfc.NameFiles=v[i].NameFiles;
            mfc.Type=v[i].Type;
            mfc.status=false;
            mfc.Path=v[i].Comment+"/"+v[i].NameFiles+"."+v[i].Type;
            cout <<"# "<<v[i].number    <<" \t"
                 <<v[i].NameFiles       <<" \t"
                 << v[i].Type           << " Что это? ";
            char Vibor;
            cin >> Vibor;
            switch (Vibor)
            {
                case 'm': DMac.push_back(mfc);   v.erase(v.begin()+i); break;
                case 'w': DWin.push_back(mfc);   v.erase(v.begin()+i); break;
                case 'p': Media.push_back(mfc);  v.erase(v.begin()+i); break;
                case 's': Sundry.push_back(mfc); v.erase(v.begin()+i); break;
                default: cout << "Некоректный ввод\n"; break;
            }
        xx=v.size();
        }
    } while (xx!=0);
    PRINT(); //!
    if (v.size()!=0) cout << "Первичный вектор не пуст, вы точно хотите продолжить?\n";
    cout << endl;
    cout << "Осталось не обработано               = "   <<v.size()<< " объектов" << endl;
    cout << "Размер очереди на копирование DMac   = "   <<DMac.size()<< " объектов" << endl;
    cout << "Размер очереди на копирование DWin   = "   <<DWin.size()<< " объектов" << endl;
    cout << "Размер очереди на копирование Media  = "   <<Media.size()<< " объектов" << endl;
    cout << "Размер очереди на копирование Sundry = "   <<Sundry.size()<< " объектов" << endl;
    if (SumMF!=(v.size()+DMac.size()+DWin.size()+Media.size()+Sundry.size()))
    {
            cout << "Что то потеряли, запускаю проверку ...\n";}else
            {
                cout << "Вроде все ОК! Продолжаем!\n";
            }
    return 0;
}
файл func.cpp:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <func.hpp>
 
bool getValueFromFile(const std::string& filename, const std::string& paramName, std::string& paramValue)
{
   std::ifstream inFile (filename); //создать поток
      if (!inFile.is_open()) //проверить открыт ли файл
      return false;
 
   paramValue.clear();
   std::string line, name;
  while (getline(inFile, line)) //прочитать строку
   {
 
       //парсим прочитанную строку файла
      name = line.substr(0, line.find(' '));
      if (name == paramName)
      {
     paramValue = line.substr(name.size() +1, line.find(';'));
     break;
      }
   }
   inFile.close();
   if (paramValue.empty())
      return false;
   return true;
}
 
void saveLogToFile(char& type, const std::string& EventLog, const bool rewrite)
{
    std::string filename;
    switch (type)
    {
    case 'e':
        filename = "log/Log_Err.txt";
        break;
    case 'l':
        filename = "log/Log.txt";
        break;
    case 'g':
        filename = "log/Log_event.txt";
        break;
   }
   std::ofstream outFile (filename, rewrite ? std::ios::out : std::ios::app); //создать поток
   if (!outFile.is_open()) std::cout << "Unable to write " << std::endl;
   outFile << EventLog << ";\n";
   outFile.close();
}
 
void GetDIR(const char *Target)
{
    char WorkDir[FILENAME_MAX];
    getcwd(WorkDir, sizeof(WorkDir));
    chdir(Target);
    DIR *dir = opendir(Target);
    if(dir)
    {
    struct dirent *ent;
 
        while((ent = readdir(dir)) != NULL)
        {
        ++mf.number;
        std::string tmp=ent->d_name;
        //Отсеиваем мусор
        auto dotPos = tmp.find('.');
        if ((dotPos + 2) >= tmp.size())
        {
            continue;
        }
        struct stat buf;
        stat((ent->d_name), &buf);
        if ((buf.st_mode &S_IFMT)==32768)
        {
            auto extPos= tmp.size()-4;
            auto eolPos =  tmp.find('\n');
            mf.Comment=Target;
            mf.NameFiles=tmp.substr(0, extPos);
            mf.Type=tmp.substr(mf.NameFiles.size()+1, eolPos);
            v.push_back(mf);
            continue;
        } else
            if ((buf.st_mode &S_IFMT)==16384)
            {
            mf.Comment=Target;
            mf.NameFiles=tmp;
            mf.Type="DIR";
            v.push_back(mf);
            continue;
            }
        }
    }else std::cout << "Error opening directory\n";
    chdir(WorkDir);
}
// Проверяем принадлежность к типам данных
inline bool checkMediaFileType(std::string const & type)
{
    static const char * types[] = {
        "avi", "mkv", "mp3", "ipg", "png"
    };
    for(char const * curType : types)
        if(type == curType)
            return true;
    return false;
}
 
inline bool checkMacFileType(std::string const & type)
{
    static const char * types[] = {
        "dmg", "pkg"
    };
    for(char const * curType : types)
        if(type == curType)
            return true;
    return false;
}
 
inline bool checkWinFileType(std::string const & type)
{
    static const char * types[] = {
        "exe", "bat", "cmd", "msi"
    };
    for(char const * curType : types)
        if(type == curType)
            return true;
    return false;
}
//Загрузка исключений из файла "Exclusion"
bool LoadExclusion()
{
    std::string filename = "Exclusion";
    std::ifstream inFile (filename); //создать поток
    if (!inFile.is_open()) //проверить открыт ли файл
    {
        std::cout<< "Файл с исключениями не найден, продолжить без него? Нет (n)\n";
        std::cin.get();
        if (std::cin.get()=='n') return false;
    }
    Excl.clear();
    myExc.Number=0;
    std::string line, name;
    while (getline(inFile, line)) //прочитать строку
        {
            //парсим прочитанную строку файла
            name = line.substr(0, line.find('\n'));
            myExc.Number++;
            myExc.Name=name;
            Excl.push_back(myExc);
        }
    inFile.close();
    std::cout << "Исключения:\n";
    for (unsigned int i=0; i<Excl.size(); ++i)
        {
            std::cout<< Excl[i].Number<< "e = " <<Excl[i].Name<<std::endl;
        }
    std::cout<<"Продолжаем ENTER, выход n\n";
    if (std::cin.get()=='n')
    {
        std::cout<<"Выход и программы\n";
        sleep(2);
        return false;
    }
    std::cout << "исключения добавлены";
    return true;
}
файл func.hpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#ifndef FUNC
#define FUNC
struct MyFiles
{
    int number;             //№ по порядку
    std::string NameFiles;  //собственно имя
    std::string Type;       //расширение нужно для последующей сортировки
    bool status;            //Отметка об удачном копировании
    std::string Comment;    //коментарии для логирования
};
MyFiles mf;
std::vector<MyFiles> v;
//для непосредственного копирования
struct MyFilesCopy
{
    int Number;
    std::string NameFiles;  //собственно имя
    std::string Type;       //расширение нужно для последующей сортировки
    bool status;            //Отметка об удачном копировании
    std::string Path;       //путь к файлу
    bool Triger;            //для ручного разбора
};
MyFilesCopy mfc;
 
//исключения
struct MyExclusion
{
    int Number;
    std::string Name;
};
MyExclusion myExc;
std::vector<MyExclusion> Excl;
 
bool LoadExclusion();
 
bool getValueFromFile(const std::string& filename, const std::string& paramName, std::string& paramValue);
 
void saveLogToFile(char& type, const std::string& EventLog, const bool rewrite);
 
void GetDIR(const char *Target);
 
inline bool checkMediaFileType(std::string const & type);
 
inline bool checkMacFileType(std::string const & type);
 
inline bool checkWinFileType(std::string const & type);
#endif // FUNC
Что бы уж точно компилируемый!
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 01:17     Интересная особенность в работе вектора #10
Mesteriis, в 2-х словах, тебе нужно использовать remove_if вместе с erase

Добавлено через 2 минуты
Mesteriis, ты понимаешь смысл минимального компилируемого кода? он должен иллюстрировать проблему, используя простые данные. я не собираюсь разбираться в твоем хламе. заполни вектор 10-ю элементами, удали все четные (к примеру), используя СВОЙ подход, как в настоящем коде.

я прошу код, дабы разговор был предметный. вот код не работает, вот я показываю как надо. ты сравниваешь, вносишь необходимые изменения в свой код.
Mesteriis
372 / 155 / 40
Регистрация: 08.08.2015
Сообщений: 1,104
Завершенные тесты: 1
10.11.2015, 01:28  [ТС]     Интересная особенность в работе вектора #11
pproger, Ладно проехали, моя вина вспылил из за dmg!
Слушай, чой то сейчасчитаю, там написано что remove_if нечего не удаляет из вектора а просто его сдвигает, и что то не могу разобратся тогда с синтаксисом, я использовал конструкцию
C++
1
v.erase(v.begin()+i);
потому что она явно указывает на элемент который надо удалить, то бишь очистить 5й от начала (допустим) а с remove_if я что то не пойму даже, если он мне его сдвинет, тоесть размер vector-a не изменится! Или я что то не понимаю!
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 01:35     Интересная особенность в работе вектора #12
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Mesteriis,
так поэтому я и просил от тебя ПРИМЕР, где демонстрируется проблема! чтож ты такой тугой то.

ладно, рассмотрим твой недокод.
ты идешь по вектору for лупом, от 0 до size. внутри цикла вызываешь erase. что делает erase? удаляет элемент и СДВИГАЕТ все, что осталось справа. представь, что у тебя такая структура, где тебе необходимо удалить 2 подряд идущих элемента (с индексами 0 и 1). начался цикл, i = 0. ты удаляешь элемент, все сдвигается влево. след итерация, i = 1, а старый первый у тебя уже нулевой! вот ты его и потерял.

компрендо?

Добавлено через 2 минуты
Mesteriis, и между прочим, Mac OS X уже несколько лет как не существует. OS X нынче.
Mesteriis
372 / 155 / 40
Регистрация: 08.08.2015
Сообщений: 1,104
Завершенные тесты: 1
10.11.2015, 01:38  [ТС]     Интересная особенность в работе вектора #13

Не по теме:

Цитата Сообщение от pproger Посмотреть сообщение
OS X нынче
Я гляжу тебя прям прет от знаний)))) Будьте проще и люди потянутся!


Про разъяснение мерси, все понял
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 01:44     Интересная особенность в работе вектора #14
Mesteriis, дальше, продолжая процесс обучения. как ты понимаешь, при каждом удалении (изменения размера вектора) может происходить перевыделение памяти. дабы оптимизировать этот момент используется т.н называемая erase-remove идиома. смысл в том, что сначала мы перемещаем все удаленные элементы в конец массива и получаем новый итератор на следующий_за_последним. потом одним вывозов erase удаляем эти элементы (и возможно в этот единственный момент память перераспределится). так то.

касательно твоего кода. я бы использовал стандартный алгоритм remove_if, проверяя в лямбде, что элемент нужно удалить. в этой же лямбде сохранял куда требуется удаленный элемент (или что ты там пытался изобразить). потом бы вызвал erase.

Добавлено через 2 минуты
Цитата Сообщение от Mesteriis Посмотреть сообщение
Я гляжу тебя прям прет от знаний
дык всегда приятно ткнуть ближнего в его же дерьмо. не знал?
gru74ik
Модератор
Эксперт CЭксперт С++
3924 / 1682 / 189
Регистрация: 20.02.2013
Сообщений: 4,743
Записей в блоге: 21
10.11.2015, 10:29     Интересная особенность в работе вектора #15
Mesteriis, вот:
1) std::vector - контейнер, который может содержать элементы одного типа (а не коллекцию разных)
2) после удаления элемента с помощью метода erase() или с помощью remove_if() используй метод shrink_to_fit()

Добавлено через 15 минут
Mesteriis, а лучше прочитай про вектора у Джосаттиса (стр. 300-314).

Добавлено через 17 минут
Mesteriis, учти, что после удаления элементов из вектора, изменения его размера и ёмкости, итераторы, указатели и ссылки станут невалидными.
Tulosba
:)
Эксперт С++
4390 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
10.11.2015, 11:30     Интересная особенность в работе вектора #16
Цитата Сообщение от pproger Посмотреть сообщение
при каждом удалении (изменения размера вектора) может происходить перевыделение памяти
При удалении такого не происходит. Собственно из-за этого и добавили shrink_to_fit
Цитата Сообщение от pproger Посмотреть сообщение
я бы использовал стандартный алгоритм remove_if
А я бы std::remove_copy_if
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 11:36     Интересная особенность в работе вектора #17
Цитата Сообщение от gru74ik Посмотреть сообщение
1) std::vector - контейнер, который может содержать элементы одного типа (а не коллекцию разных)
а что, в крестах бывают гетерогенные контейнеры?
Цитата Сообщение от gru74ik Посмотреть сообщение
после удаления элемента с ... помощью remove_if() используй метод shrink_to_fit()
ничо не даст.

Добавлено через 3 минуты
Цитата Сообщение от Tulosba Посмотреть сообщение
А я бы std::remove_copy_if
он модифицирует удаленные элементы. а не просто копирует.

Цитата Сообщение от Tulosba Посмотреть сообщение
При удалении такого не происходит
есть мнение, что это implementation defined
gru74ik
Модератор
Эксперт CЭксперт С++
3924 / 1682 / 189
Регистрация: 20.02.2013
Сообщений: 4,743
Записей в блоге: 21
10.11.2015, 11:39     Интересная особенность в работе вектора #18
Цитата Сообщение от pproger Посмотреть сообщение
ничо не даст.
Размер и ёмкость будет совпадать, по крайней мере.

Добавлено через 3 минуты
А как вообще можно бороться с тем, что итераторы становятся невалидными? Есть какие-то способы решить эту проблему (ну кроме как заранее место резервировать с помощью reserve() )?
pproger
163 / 66 / 13
Регистрация: 22.03.2011
Сообщений: 188
10.11.2015, 11:45     Интересная особенность в работе вектора #19
Цитата Сообщение от gru74ik Посмотреть сообщение
Размер и ёмкость будет совпадать, по крайней мере.
это может быть и минусом. аллокатор старается, понимаешь ли, с запасом выделяет память для будущих элементов, а тут нна, и вся работа на смарку. вобщем, вредный совет на мой взгляд.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.11.2015, 12:05     Интересная особенность в работе вектора
Еще ссылки по теме:

C++ Не изменяется элемент вектора при работе с ним по указателю
C++ Особенность объявления функции
C++ Интересная конструкция в C++
C++ В чем особенность функции типа void от других типов?
Интересная задача на графы C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Tulosba
:)
Эксперт С++
4390 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
10.11.2015, 12:05     Интересная особенность в работе вектора #20
Цитата Сообщение от pproger Посмотреть сообщение
он модифицирует удаленные элементы. а не просто копирует.
С remove_copy_if я, конечно, погорячился. Однако элементы он не модифицирует:
Copies the elements in the range [first,last) to the range beginning at result, except those elements for which pred returns true.
Для условного переноса элементов из одного контейнера в другой нужно что-то такого вида:
C++
1
2
3
4
5
std::vector<int> v;
// ...
auto it = std::stable_partition(v.begin(), v.end(), pick_the_good_elements);
std::vector<int> w(std::make_move_iter(it), std::make_move_iter(v.end()));
v.erase(it, v.end());
Отсюда. Там же есть и другое решение.
Цитата Сообщение от pproger Посмотреть сообщение
есть мнение, что это implementation defined
Ошибочное мнение. 23.3.6.5/3:
Invalidates iterators and references at or after the point of the erase.
Т.о. до точки удаления итераторы и ссылки не портятся. Стало быть перевыделения быть не может.

Добавлено через 1 минуту
Цитата Сообщение от gru74ik Посмотреть сообщение
бороться с тем, что итераторы становятся невалидными?
Не допускать соответствующих действий.
Насчет инвалидации много полезного тут.
Yandex
Объявления
10.11.2015, 12:05     Интересная особенность в работе вектора
Ответ Создать тему
Опции темы

Текущее время: 23:28. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru