Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
44 / 44 / 24
Регистрация: 01.05.2012
Сообщений: 178
1

Работа с векторами без использования STL и библиотеки <vector>

04.04.2016, 19:48. Показов 3635. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте Уважаемые формучане. Подскажите пожалуйста, есть ли смысл писать свой собственный класс Vector если из него всё равно будет выходить подобие STL?

В универе препод дал такое задание. Hо, я как не напишу свой класс Vector у меня всё равно выходит подобие STL.

Есть ли смысл тогда его вообще писать если он не будет защищен от внутренних проверок (например, выход элемента за границу вектора) или проще использовать стандартную библиотеку?
C++
1
<vector>
Помогите пожалуйста советом.

Я в итоге программу написал, но с использованием STL и <vector>.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.04.2016, 19:48
Ответы с готовыми решениями:

Переделать программу без использования библиотеки <vector>
Доброго времени. Программа не моя, но немного переделанная, нашел её здесь. Хотелось бы её увидеть...

Как реализовать стек из Stl в программе без использования библиотеки
Мне нужно реализовать стек из Stl, без использования библиотеки. Я немного не понимаю, как это...

Работа с файлом без использования библиотеки cstdio
Добрый день! Было дано задание: создать файл и работать с ним без использования библиотеки...

Работа со строками. Переписать программу без использования библиотеки <sstream>
Добрый день! Помогите пожалуйста преобразовать программу, которая заменяет выбранное вами слово на...

8
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
04.04.2016, 20:29 2
Смысл писать свой аналог контейнера из STL вижу в двух случаях: а) для обучения, чтобы понять, что у STL "под капотом"; б) когда есть свои довольно-таки специфические потребности, которым STL не соответствует, а надо, и при этом ещё есть достаточно твёрдые знания предмета и уверенность, что получится не хуже. Во втором случае, конечно же, уверенность крайне желательно проверить сравнительными испытаниями и исчерпывающим тестированием.
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
04.04.2016, 20:37 3
Цитата Сообщение от Sigma214 Посмотреть сообщение
Помогите пожалуйста советом.
По разному. Зависит от потребностей. У меня к примеру vector в его исходном виде никогда не использовался, как миниму допиливался кое-какой функционал. Ну и еще один ньюанс - вектор кое в чем очень безграмотно спроектирован. Объясню в чем. Если динамический массив имеет функцию добавления элемента, то во избежания проблем с быстродействием и фрагментацией памяти шаг роста при ресайзе должен быть управляемым, а допиливание такого в std::vector тянет на полную его переделку. Опять же возможны разные вариации на тему вектора. Например массивы работающее по типу указателей. т.е. сам массив не хранит данные а только ссылку на буфер данных, который ведет подсчет ссылок. При присваивании массивы не копируются, копируется только указатель на буфер. В результате поведение таких массивов соответствует обычным указателям, только со всеми плюшками динамического массива, что в некоторых случаях позволяет экономить память а так же получить при некоторых задачах гораздо более высокое быстродействие, нежели плодя копии данных как это делает std::vector. Опять же под хранение списков указателей на объекты удобнее сделать специализированный для них контейнер, нежели пользовать std::vector<unique_ptr<>> или std::vector<shared_ptr<>>, а особенно если эти списки должны поддерживать сериализацию/десериализацию полиморфного контента.

Цитата Сообщение от Sigma214 Посмотреть сообщение
Есть ли смысл тогда его вообще писать если он не будет защищен от внутренних проверок (например, выход элемента за границу вектора)
Есть смысл сделать проверку выхода за границы отключаемой в релизе. У std::vector есть доступ как с проверкой так и без проверки границ. Но к сожалению не переключаемый автоматически при смене конфигурации Debug/Release

Добавлено через 3 минуты
Цитата Сообщение от Nick Alte Посмотреть сообщение
а) для обучения, чтобы понять, что у STL "под капотом";
Вот то то и оно. Потому что когда понадобится пункт б пункт а будет просто необходим.
0
44 / 44 / 24
Регистрация: 01.05.2012
Сообщений: 178
04.04.2016, 22:21  [ТС] 4
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
std
по заданию мне запрещено использовать <vector> и STL. Но можно использовать std.
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
04.04.2016, 22:25 5
Цитата Сообщение от Sigma214 Посмотреть сообщение
по заданию мне запрещено использовать <vector> и STL. Но можно использовать std.
std это неймспейс STL. Сделать свой класс все равно полезно. Говорю по собственному опыту. Ну правда когда мне такие задания не препады давали, а они вытекали из тех заданий которые давали препады, STL еще и в помине не существовало, поэтому приходилось самостоятельно весь этот набор организовывать. Зато потом сразу видно для чего набор того что есть в stl применим и эффективен, а для чего его лучше не использовать.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.04.2016, 21:22 6
Цитата Сообщение от Sigma214 Посмотреть сообщение
Подскажите пожалуйста, есть ли смысл писать свой собственный класс Vector если из него всё равно будет выходить подобие STL?
это полезно на этапе обучения.

Цитата Сообщение от Sigma214 Посмотреть сообщение
Есть ли смысл тогда его вообще писать если он не будет защищен от внутренних проверок (например, выход элемента за границу вектора) или проще использовать стандартную библиотеку?
вы, наверное, имели ввиду,
если он не будет защищен внутренними проверками.
я б такую халтуру вообще бы не принял.
0
Падаван С++
447 / 261 / 89
Регистрация: 11.11.2014
Сообщений: 916
07.04.2016, 14:38 7
Sigma214, ТС`у, тут какие то не шуточные споры, но для практики преподаватель тоже давал задание написать свой вектор, если нужно то вот что я делал
Кликните здесь для просмотра всего текста
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
template <class T> class iterator {
    protected:
        T *ptr;
    public:
        iterator() : ptr(nullptr) {}
        iterator(T* ptr) : ptr(ptr) {}
        virtual ~iterator() { if (ptr != nullptr) delete[] ptr; }
        T& operator*() { return *ptr; }
        T* operator->() { return ptr; }
        bool operator==(const iterator& other) const { return ptr == other.ptr; }
        bool operator!=(const iterator& other) const { return !(*this == other); }
    };
    template <class T> class std_iterator : public iterator<T> {
    public:
        std_iterator() : iterator<T>() {}
        std_iterator(T* ptr) : iterator<T>(ptr) {}
        T* operator++() { return ++ptr; }
        T* operator--() { return --ptr; }
        T* operator+(int i) { return ptr + i; }
        T* operator-(int i) { return ptr - i; }
    };
    template <class T> class reverse_iterator : public iterator<T> {
    public:
        reverse_iterator() : iterator<T>() {}
        reverse_iterator(T* ptr) : iterator<T>(ptr) {}
        virtual T* operator++() override final { return --ptr; }
        virtual T* operator--() override final { return ++ptr; }
        virtual T* operator+(int i) override final { return ptr - i; }
        virtual T* operator-(int i) override final { return ptr + i; }
    };
    template <class T> class const_std_iterator : public std_iterator<T> {
    public:
        const_std_iterator(T* ptr) : std_iterator<T>(ptr) {}
        const T& operator*() { return *ptr; }
        const T* operator->() { return ptr; }
    };
    template <class T> class const_reverse_iterator : public reverse_iterator<T> {
    public:
        const_reverse_iterator(T* ptr) : reverse_iterator<T>(ptr) {}
        const T& operator*() { return *ptr; }
        const T* operator->() { return ptr; }
    };
    template <class T> class myVector {
    private:
        typedef unsigned int uInt;
        T * m_Data;
        uInt m_Size;
    public:
        myVector(void);
        ~myVector(void);
        myVector(const T*, const uInt);
        myVector(const myVector&);
 
        T& operator[](const uInt);
        myVector & operator=(const myVector&);
 
        inline std_iterator<T> begin(void);
        inline std_iterator<T> end(void);
        inline reverse_iterator<T> rbegin(void) const;
        inline reverse_iterator<T> rend(void) const;
        inline const_std_iterator<T> cbegin(void) const;
        inline const_std_iterator<T> cend(void) const;
        inline const_reverse_iterator<T> crbegin(void) const;
        inline const_reverse_iterator<T> crend(void) const;
 
        void resize(const uInt);
        void resize(const uInt, const T);
        inline auto size(void) const;
        inline auto capacity(void) const;
        auto empty(void) const;
 
        void setData(const T*, const uInt);
        inline T* data(void) const;
        inline T& front(void) const;
        inline T& at(const uInt) const;
        inline T& back(void) const;
 
        void clear(void);
        void pop_back(void);
        void push_back(const T);
        void erase(const uInt);
        void erase(const std_iterator<T>);
        void swap(const uInt, const uInt);
        void insert(const T, const uInt);
        void assign(const T, const uInt);
        void assign(const std_iterator<T>, const std_iterator<T>);
    };
    template <class T> class my_unique_ptr {
    private:
        T * ptr;
        my_unique_ptr(my_unique_ptr & elem) {
        }
        my_unique_ptr & operator=(my_unique_ptr & elem) {
        }
    public:
        my_unique_ptr(void) : ptr(nullptr) {
        }
        ~my_unique_ptr(void) {
            delete[] ptr;
        }
 
        T& operator*(void) { return *ptr; }
        T* operator->(void) { return ptr; }
        bool operator==(my_unique_ptr & elem) { return ptr == elem.ptr; }
        bool operator!=(my_unique_ptr & elem) { return ptr != elem.ptr }
 
        T * relise(void) {
            T * tmp = ptr;
            ptr = nullptr;
            return tmp;
        }
        void reset(T * obj) {
            if (ptr != nullptr) delete[] ptr;
            ptr = obj;
        }
        void swap(my_unique_ptr & obj) {
            T * tmp = ptr;
            ptr = obj.ptr;
            obj.ptr = tmp;
        }
 
        T* get(void) { return ptr; }
    };
    template <class T> myVector<T>::myVector(void) : m_Size(0), m_Data(nullptr) {
    }
    template <class T> myVector<T>::~myVector(void) {
        if (m_Data != nullptr) delete[] m_Data;
    }
    template <class T> myVector<T>::myVector(const T * Data, const uInt Size) : m_Data(nullptr), m_Size(0) {
        setData(Data, Size);
    }
    template <class T> myVector<T>::myVector(const myVector & obj) : m_Data(nullptr), m_Size(0) {
        setData(obj.m_Data, obj.m_Size);
    }
 
    template <class T> T& myVector<T>::operator[](const uInt index) {
        return m_Data[index];
    }
    template <class T> myVector<T>& myVector<T>::operator=(const myVector & elem) {
        if (&elem == this) return *this;
        if (m_Data != nullptr) delete[] m_Data;
        setData(elem.m_Data, elem.m_Size);
        return *this;
    }
 
    template <class T> inline std_iterator<T> myVector<T>::begin(void) { return m_Data; }
    template <class T> inline std_iterator<T> myVector<T>::end(void) { return m_Data + m_Size; }
    template <class T> inline const_std_iterator<T> myVector<T>::cbegin(void) const { return m_Data; }
    template <class T> inline const_std_iterator<T> myVector<T>::cend(void) const { return m_Data + m_Size; }
    template <class T> inline reverse_iterator<T> myVector<T>::rbegin(void) const { return m_Data + m_Size - 1; }
    template <class T> inline reverse_iterator<T> myVector<T>::rend(void) const { return m_Data - 1; }
    template <class T> inline const_reverse_iterator<T> myVector<T>::crbegin(void) const { return m_Data + m_Size - 1; }
    template <class T> inline const_reverse_iterator<T> myVector<T>::crend(void) const { return m_Data - 1; }
 
    template <class T> void myVector<T>::resize(const uInt Size) {
        T * tmp = new T[Size];
        for (int i(0); i < m_Size; i++)
            tmp[i] = m_Data[i];
 
        delete[] m_Data;
        m_Data = tmp;
        m_Size = Size;
    }
    template <class T> void myVector<T>::resize(const uInt Size, const T value) {
        T * tmp = new T[Size];
        for (int i(0); i < m_Size; i++)
            tmp[i] = m_Data[i];
        for (int i(m_Size); i < Size; i++)
            tmp[i] = value;
 
        delete[] m_Data;
        m_Data = tmp;
        m_Size = Size;
    }
    template <class T> inline auto myVector<T>::size(void) const { return m_Size; }
    template <class T> inline auto myVector<T>::capacity(void) const { return sizeof(m_Data[0]); }
    template <class T> auto myVector<T>::empty(void) const { return m_Size == 0 ? true : false; }
 
    template <class T> void myVector<T>::setData(const T * Data, const uInt Size) {
        m_Size = Size;
        if (m_Data != nullptr) delete[] m_Data;
        m_Data = new T[m_Size];
        for (int i(0); i < m_Size; i++)
            m_Data[i] = Data[i];
    }
    template <class T> inline T* myVector<T>::data(void) const { return m_Data; }
    template <class T> inline T& myVector<T>::front(void) const { return m_Data[0]; }
    template <class T> inline T& myVector<T>::at(const uInt index) const { return m_Data[index]; }
    template <class T> inline T& myVector<T>::back(void) const { return m_Data[m_Size - 1]; }
 
    template <class T> void myVector<T>::clear(void) {
        m_Size = 0;
        delete[] m_Data;
        m_Data = nullptr;
    }
    template <class T> void myVector<T>::pop_back(void) {
        m_Size--;
        T * tmp = new T[m_Size];
        for (int i(0); i < m_Size; i++)
            tmp[i] = m_Data[i];
 
        delete[] m_Data;
        m_Data = tmp;
    }
    template <class T> void myVector<T>::push_back(const T elem) {
        T * tmp = new T[m_Size + 1];
        for (int i(0); i < m_Size; i++)
            tmp[i] = m_Data[i];
        tmp[m_Size] = elem;
 
        delete[] m_Data;
        m_Data = tmp;
        m_Size++;
    }
    template <class T> void myVector<T>::erase(const uInt index) {
        for (int i(index); i < m_Size - 1; i++)
            m_Data[i] = m_Data[i + 1];
 
        T * tmp = new T[m_Size - 1];
        for (int i(0); i < m_Size - 1; i++)
            tmp[i] = m_Data[i];
 
        delete[] m_Data;
        m_Data = tmp;
        m_Size--;
    }
    template <class T> void myVector<T>::erase(std_iterator<T> iter) {
        int num;
        for (int i(0); i < m_Size; i++)
            if (iter == &m_Data[i]) {
                num = i;
                break;
            }
 
        for (int i(num); i < m_Size - 1; i++)
            m_Data[i] = m_Data[i + 1];
 
        T * tmp = new T[m_Size - 1];
        for (int i(0); i < m_Size - 1; i++)
            tmp[i] = m_Data[i];
 
        delete[] m_Data;
        m_Data = tmp;
        m_Size--;
    }
    template <class T> void myVector<T>::swap(const uInt from, const uInt with) {
        T tmp = m_Data[from];
        m_Data[from] = m_Data[with];
        m_Data[with] = tmp;
    }
    template <class T> void myVector<T>::insert(const T elem, const uInt position) {
        T * tmp = new T[m_Size + 1];
        for (int i(0); i < m_Size; i++)
            tmp[i] = m_Data[i];
 
        for (int i(m_Size); i > position; i--)
            tmp[i] = tmp[i - 1];
 
        tmp[position] = elem;
 
        delete[] m_Data;
        m_Data = tmp;
        m_Size++;
    }
    template <class T> void myVector<T>::assign(T elem, const uInt Size) {
        m_Size = Size;
        if (m_Data != nullptr) delete[] m_Data;
        m_Data = new T[m_Size];
        for (int i(0); i < m_Size; i++)
            m_Data[i] = elem;
    }
    template <class T> void myVector<T>::assign(std_iterator<T> first, std_iterator<T> last)
    {
        int i = 0;
        for (auto it = first; it != last; ++it, i++);
        m_Size = i;
        if (m_Data != nullptr) delete[] m_Data;
        m_Data = new T[m_Size];
        i = 0;
        for (auto it = first; it != last; ++it, i++)
            m_Data[i] = *it;
    }

может что возьмете, не лучшее и не очень оптимизированное исполнение, но вроде работает
P.S помойму тут не финальная версия, и я там накосячил с итераторами немного, ну если нужно будет поправите
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
08.04.2016, 04:00 8
Цитата Сообщение от obivan Посмотреть сообщение
не лучшее и не очень оптимизированное исполнение
первая простейшая оптимизация с очисткой:
C++
1
2
3
    
inline void Pack(){Capacity=Count;};
inline void Clear(bool DoPack=false){Count=0; if (DoPack) Pack();};
Дает возможность только логической очистки и повторного использования уже выделенной памяти при повторном использовании вектора.
Цитата Сообщение от obivan Посмотреть сообщение
и я там накосячил с итераторами немного, ну если нужно будет поправите
Естественно. Зачем итератор в деструкторе удаляет элемент на который укзывает? он только указатель а не владелец элемента, соответственно и удалять ничего не должен. А так вот такой код
C++
1
2
3
4
5
6
7
void main(){
     myVector<int> a;
     // .....заполнение вектора;
     { 
              auto b=a.begin();
     } // вот здесь удалит буфер данных вектора.
}
0
tezaurismosis
09.04.2016, 19:25     Работа с векторами без использования STL и библиотеки <vector>
  #9
 Комментарий модератора 
Весь оффтоп о внутренностях стандартной библиотеки вынесен в отдельную тему: О деталях и возможностях реализации <vector>
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.04.2016, 19:25

Создание конфигурации-аналога 'Мини-библиотеки'. Работа со статусами книг без использования регистров.
Доброго времени суток! Мне нужен совет, а еще лучше пример, как сделать следующее: У меня...

Работа с векторами (<vector>)
Здравствуйте, уважаемы программисты))) Кто бы мог мне помочь в таком вопросе: при использовании...

Работа с STL vector
Добрый день! Прошу объяснить следующие моменты связанные с &lt;vector&gt; (почему ругается студия,...

Работа с STL. Поменять vector на list
Программа должна быть написана так, чтобы достаточно было заменить в одном месте vector на list и...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru