Форум программистов, компьютерный форум, киберфорум
Тамика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  

Ещё чуть-чуть вектора.

Запись от Тамика размещена 01.07.2014 в 13:35
Показов 3781 Комментарии 6
Метки c++

Всем бобрового утра!
Кто читает это уже не утром - бобрового дня или вечера.
Так вот.
Скучным рабочим утром решила стряхнуть пыль с проекта под названием int_array. И малость его доработать.
Были внесены следующие изменения:
1) Убрана недоработка, на которую указал SatanaXIII.
2) Использованы ценные советы Jupiter.
3) Усовершенствован конструктор - теперь он не просто принимает размер будущего вектора, а может еще и принимать желаемое значение!
4) Изменила возвращаемые значения у getSize() и getCapacity - раз уж они у нас должны быть более нуля, то сняла их с int и посадила на size_t.

Изменения не существенны, однако это ещё один шаг к улучшению вектора.
В следующем сезоне "Таня и Вектор" - обобщение класса и превращение его в шаблон.

И снова внимательно прислушиваюсь к комментариям старших. Спасибо за внимание!

Итак.
Сосбна, хедерок.
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
#pragma once
#include <stdexcept>
#include <algorithm> 
 
class IntVector
{
    int *mas;
    size_t size, capacity;
public:
    
    IntVector();
 
    ~IntVector();
 
    IntVector(const IntVector& in);
 
    explicit IntVector(const size_t aSize, const int val = 0);
 
    size_t getSize() const;
 
    size_t getCapacity() const;
 
    void resize(size_t n);
 
    void reserve(size_t n);
 
    void pushBack(int val);
 
    void popBack();
 
    int& operator[] (size_t n);
 
    const int& operator[] (size_t n) const;
 
    int& at(size_t n);
 
    IntVector& operator= (const IntVector& in);
 
    void clear();
 
    void erase(size_t index);
 
    bool empty() const;
 
    int front() const;
 
    int back() const;
 
    int& front();
 
    int& back();
 
    void swap (IntVector &in) throw ();
};
А теперь сама начинка.
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
#include "int_array.h" 
 
 
IntVector::~IntVector()
{
    delete [] mas;
}
 
IntVector::IntVector() : mas(0), size(0), capacity(0)
{
}
 
IntVector::IntVector(const IntVector& in)
{
    size = in.size;
    capacity = in.capacity;
    mas = new int[capacity];
    for (int i = 0; i < size; ++i)
        mas[i] = in.mas[i];
}
 
IntVector::IntVector(const size_t aSize, const int val)
{
    mas = new int[aSize];
    size = aSize;
    capacity = aSize;
    for (int i = 0; i < size; ++i)
        mas[i] = val;
}
 
size_t IntVector::getSize() const
{
    return size;
}
 
size_t IntVector::getCapacity() const
{
    return capacity;
}
 
void IntVector::reserve(size_t n)
{
    if (n > capacity)
    {
        int *temp = new int[n];
        capacity = n;
        for (int i = 0; i < size; ++i)
            temp[i] = mas[i];
        delete []mas;
        mas = temp;
    }
}
 
void IntVector::resize(size_t n)
{
    if (size > n)
    {
        size = n;
        return;
    }
    if (size < n)
    {
        reserve(n);
        for (int i = size; i < n; ++i)
            mas[i] = 0;
    }
}
 
void IntVector::pushBack(int val)
{
    if (size >= capacity)
    {
        size_t new_size = size + 1;
        reserve(new_size + new_size / 2);
    }
    mas[size++] = val;
}
 
void IntVector::popBack()
{
    if (size >= 1)
        --size;
}
 
int& IntVector::operator[] (size_t n)
{
    return mas[n];
}
 
const int& IntVector::operator[] (size_t n) const
{
    return mas[n];
}
 
int& IntVector::at(size_t n)
{
    if (n >= size)
        throw std::out_of_range("Index out of range!");
    return mas[n];
}
 
IntVector& IntVector::operator= (const IntVector& in)
{
    IntVector temp(in);
    temp.swap(*this);
    return *this;
}
 
void IntVector::swap(IntVector& in) throw()
{
    std::swap(mas, in.mas);
    std::swap(size, in.size);
    std::swap(capacity, in.capacity);
}
 
void IntVector::clear()
{
    size = 0;
}
 
void IntVector::erase(size_t index)
{
    if (index >= size) 
        throw std::out_of_range("Index out of range!");
    --size;
    for (int i = index; i < size; ++i)
        mas[i] = mas[i + 1];
}
 
bool IntVector::empty() const
{
    return size == 0;
}
 
int IntVector::front() const
{
    return mas[0];
}
 
int IntVector::back() const
{
    return mas[size-1];
}
 
int& IntVector::front()
{
    return mas[0];
}
 
int& IntVector::back()
{
    return mas[size-1];
}
Метки c++
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 6
Комментарии
  1. Старый комментарий
    Аватар для SatanaXIII
    1) Я ж вот здесь вот как-то говорил уже, что раз есть throw() в описании, то должен быть и в реализации в реализации. Это ж две разные функции получаются:
    C++
    1
    2
    
    void IntVector::swap(IntVector& in)
    void IntVector::swap(IntVector& in) throw()
    Представленный код тупо не запустится.

    2) Вот это вот замечание HighPredator тоже прошло без внимания. Зачем два механизма? Дефайнов вполне достаточно.

    3) Многие старые компиляторы не подключают по умолчанию заголовки для работы с size_t. Можно перед классом это проверить. Хотя заместо этого так же можно и подключаемые модули перенести в хедер. Они-то обладают знаниями о size_t.
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    //#include <stdexcept>
    //#include <algorithm>
     
    #ifndef __STDDEF_H
    #include <stddef.h>
    #endif
     
    class IntVector
    {
        int *mas;
        size_t size, capacity;
    public:
    4) Зачем опять указывать область видимости внутри себя же:
    C++
    11
    
    /*IntVector::*/IntVector();
    5) Метод resize просто выбрасывает кусок памяти, если новый размер меньше старого, что приведет к утечкам. Лучше использовать какой-нибудь метод типа erase_item для каждого элемента. Но это забегая вперед.

    6) Метод clear тоже самое. Даже массив не очищает.

    7) Ну и чтобы было чем заняться после прикручивания шаблона - итератор.

    8) P.S. Ыыыыы:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    #ifndef __STDARG_H
    #include <stdarg.h>
    #endif
     
    IntVector::IntVector( int count, int item, ... ) : size(0), capacity(count)
    {
        mas = new int[count];
     
        va_list p;
        va_start( p, count );
     
        while( count-- )
          this->pushBack( va_arg( p, int ) );
     
        va_end(p);
    }
    За заполнение вектора списком без примочек одиннадцатого стандарта многие б сказали спасибо.
    Запись от SatanaXIII размещена 02.07.2014 в 14:33 SatanaXIII вне форума
  2. Старый комментарий
    Цитата Сообщение от SatanaXIII
    Некоторые пункты подправила, спасибо.
    По поводу resize и clear - совсем непонятно. Никаких утечек там не предвидится. С чего Вы взяли?
    Запись от Тамика размещена 02.07.2014 в 15:04 Тамика вне форума
  3. Старый комментарий
    Аватар для SatanaXIII
    Цитата Сообщение от Тамика
    Никаких утечек там не предвидится.
    А что будет, если в данный вектор положить не целые числа, а, к примеру, объекты некоего класса, захватывающие при инициализации ресурсы? Освободятся ли они, если просто о них забыть?
    P.S. Метод popBack кстати в ту же кучу.
    Запись от SatanaXIII размещена 02.07.2014 в 16:19 SatanaXIII вне форума
  4. Старый комментарий
    Аватар для SatanaXIII
    Хотя нет. Я не прав. Всем этим должен заниматься кончено же деструктор.

    Но метод swap, выполненный через std::swap, это конечно лихо.
    Запись от SatanaXIII размещена 02.07.2014 в 16:50 SatanaXIII вне форума
  5. Старый комментарий
    Цитата Сообщение от SatanaXIII
    Хотя нет. Я не прав. Всем этим должен заниматься кончено же деструктор.

    Но метод swap, выполненный через std::swap, это конечно лихо.
    Ну вот.
    А со swap ещё будет беседа. Еще прошлый раз думала написать свой. Но руки не дошли. Так что в следующей серии будет персональный своп.
    Запись от Тамика размещена 02.07.2014 в 16:57 Тамика вне форума
  6. Старый комментарий
    Аватар для Croessmah
    Внесу свою лепту:
    нет const версии at, в результате чего нельзя использовать at у константных объектов:
    C++
    1
    2
    
       const IntVector vec ;
       int value = vec.at(3) ; //Ошибка vec - константный объект
    В циклах сравнивание значения типа int со значением типа size_t. Чем это чревато? Тем, что если в переменной size_t лежит значение больше максимального значения, представимого типом int, то цикл будет бесконечным, т.к. переменная типа int просто будет переполняться и "уходить в минуса". Попробуйте просто для примера:
    C++
    1
    2
    3
    4
    5
    
    int main(){
       size_t f = static_cast<size_t>( std::numeric_limits<int>::max() ) + 1 ;
       for ( int i = 0 ; i < f ; i+=10000 )
          std::cout << i << std::endl ;
    }
    Также, нет ограничения на максимальный размер. Вектор не может быть бесконечным

    В стандартном векторе константные front и back возвращают ссылки на элемент, а не копии объектов:
    C++
    1
    2
    
          const_reference back() const;
    const_reference front() const;

    В конструкторе копий:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    
    IntVector::IntVector(const IntVector& in)
    {
        size = in.size;
        capacity = in.capacity;
        mas = new int[capacity];
        for (int i = 0; i < size; ++i)
            mas[i] = in.mas[i];
    }
    наверное, лучше будет уравнять size и capacity, иначе невозможно будет "обрезать" память как в стандартном векторе с помощью swap'а
    C++
    1
    
    IntVector(vec).swap(vec) ;//capacity не изменяется.
    Усовершенствован конструктор - теперь он не просто принимает размер будущего вектора, а может еще и принимать желаемое значение!
    Можно еще реализовать конструктор, принимающий интервал [begin,end)
    В следующем сезоне "Таня и Вектор" - обобщение класса и превращение его в шаблон.
    С учетом этого нужно было сразу делать, иначе придется почти весь класс переписать. И это относится не только к изменению типа int на T, а придется переосмыслить структуру всего класса
    Запись от Croessmah размещена 06.07.2014 в 20:43 Croessmah вне форума
 
Новые блоги и статьи
[golang] Двоичная куча, min-heap
alhaos 20.05.2026
Двоичная куча Двоичная куча — структура данных, которая всегда держит самый важный элемент наготове. Представьте очередь к хилеру в игре, и очередь из игроков в приоритете те у кого меньше. . .
[golang] Breadth-First Search
alhaos 19.05.2026
BFS (Breadth-First Search) — это базовый алгоритм обхода графа в ширину, который поуровнево исследует все связанные вершины. Он начинает с выбранной точки и проверяет всех соседей, прежде чем. . .
[golang] Алгоритм «Хак Госпера»
alhaos 17.05.2026
Алгоритм «Хак Госпера» Хак Госпера (Gosper's Hack) — алгоритм нахождения следующего по величине числа с тем же количеством установленных бит. Придуман Биллом Госпером в 1970-х, опубликован в. . .
Рисование бинарного древа до 6-го колена на js, svg.
russiannick 17.05.2026
<svg width="335" height="240" viewBox="0 0 335 240" fill="#e5e1bb"> <style> <!]> </ style> <g id="bush"> </ g> </ svg> function fn(){ let rost;/ / высота древа let xx=165,yy=210,w=256;
FSharp: interface of module
DevAlt 16.05.2026
Интерфейс модуля F# позволяет управлять доступностью членов, содержащихся в реализации модуля. По-умолчанию все члены модуля доступны: module Foo let x = 10 let boo () = printfn "boo" . . .
Хитросплетение родственных связей пантеона греческих богов.
russiannick 14.05.2026
Однооконник, позволяющий узреть и изучить отдельных героев древней Греции. <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible". . .
[golang] Угол между стрелками часов
alhaos 12.05.2026
По заданным значениям часа и минуты необходимо определить значение меньшего угла между стрелками аналогового циферблата часов. import "math" func angleClock(hour int, minutes int) float64 { . . .
Debian 13: Установка Lazarus QT5
ВитГо 09.05.2026
Эта инструкция моя компиляция инструкций volvo https:/ / www. cyberforum. ru/ blogs/ 203668/ 10753. html и его же старой инструкции по установке Lazarus с gtk2. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru