Форум программистов, компьютерный форум, киберфорум
Наши страницы
Тамика
Войти
Регистрация
Восстановить пароль
Оценить эту запись

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

Запись от Тамика размещена 01.07.2014 в 13:35
Обновил(-а) Тамика 02.07.2014 в 15:01

Всем бобрового утра!
Кто читает это уже не утром - бобрового дня или вечера.
Так вот.
Скучным рабочим утром решила стряхнуть пыль с проекта под названием 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];
}
Размещено в Без категории
Просмотров 730 Комментарии 6
Всего комментариев 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 вне форума
    Обновил(-а) Croessmah 06.07.2014 в 21:02
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru