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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 37, средняя оценка - 4.68
Kreativ
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
#1

Проверить на выход за границы массива - C++

05.05.2013, 12:39. Просмотров 5696. Ответов 44
Метки нет (Все метки)

ПРивет, помогите пожалуйста, пишу класс - динамический массив, в перегрузке оператора [] нужно проверить на выход за границы, но не знаю как правильно использовать try, catch, throw.
C++
1
2
3
4
5
6
7
8
9
10
11
template <class T, int size>
T & Array<T, size> :: operator [](int index) {
    try {
    if (index < 0 || index >= currentSize)
        throw out_of_range("Index was out of range");
    }
    catch(...) { // что тут писать чтобы поймать из throw
        cout << "error";
    }
    return aPtr[index]; // и как быть тут куда вставить эту строку
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.05.2013, 12:39
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Проверить на выход за границы массива (C++):

Выход за границы массива - C++
Выхожу за пределы массива, но вот только не понимаю как. #include &lt;iostream&gt; #include &lt;fstream&gt; using namespace std; const...

Массивы: Проверка на выход за границы массива - C++
Здравствуйте! Пишу код хождения коня по шахматной доске. Конь пока стоит на одном месте и ходит по кругу. Как можно реализовать проверку на...

Исправить выход за границы двумерного динамического массива - C++
Уважаемые форумчане, помогите, проблема в том, что пишет ошибку после выполнения функции вывода массива, вот код //распечатка матрицы ...

Почему происходит выход за границы массива в функции Analyze()? - C++
#include &quot;Analyzer.h&quot; #include &quot;HashTable.h&quot; #include &lt;iostream&gt; #include &lt;iomanip&gt; using namespace std; ...

При вызове функции необработанное исключение, выход за границы массива - C++
bool checkprocessed(point data,int xx,int yy,int wind) { bool mark=false; int s=0; for(int k=xx; k&lt;xx+wind;k++){ for(int...

Выход итератора за границы list - C++
почему у меня падает программа, когда пытаюсь ввести отсортированные элементы в другой list ??? list&lt;char&gt;ch; list&lt;char&gt;rev; ...

44
Kreativ
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
06.05.2013, 01:00  [ТС] #31
теперь я обязательно должен это сделать )
0
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
06.05.2013, 01:14 #32
Как сделаете, вперёд читать про RAII и умные указатели Так называется общий к вот таким штукам.
0
Kreativ
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
06.05.2013, 18:48  [ТС] #33
наброски класса сделал, только проблема с деструктором, вот сам класс:
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
#ifndef Ex_h
#define Ex_h
 
#include <iostream>
#include "TArray.h"
 
using namespace std;
 
template <class T, size_t size> class Array;
 
template <class T, size_t size>
class Ex {
    public:
        Ex(size_t s);
        ~Ex();
        void init(const T &elem, size_t n);
        T * get(void);
 
    private:
        size_t s;
        T *p;
};
 
 
template <class T, size_t size>
Ex<T, size> :: Ex(size_t s) {
    this -> s = s;
    p = reinterpret_cast<T*>(operator new[](s * sizeof(*p)));
}
 
 
template <class T, size_t size>
Ex<T, size> :: ~Ex() {
    //delete [] p;
}
 
 
template <class T, size_t size>
void Ex<T, size> :: init(const T &elem, size_t n) {
    new (p + n) T(elem);
    cout << *(p + n) << " "; 
}
 
 
template <class T, size_t size>
T * Ex<T, size> :: get(void) {
    return p;
}
 
#endif
и перегруженный оператор = в моем шаблоне:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class T, size_t size>
Array<T, size> & Array<T, size> :: operator = (const Array<T, size> &arrayForAssign) {
    if (this != &arrayForAssign) {
        Ex<T, 5> obj(arrayForAssign.currentSize);
        for (size_t i = 0; i < arrayForAssign.currentSize; i++) {
            obj.init(arrayForAssign.aPtr[i], i);
        }       
        delete [] aPtr;
        aPtr = obj.get();
        currentSize = arrayForAssign.currentSize;
        maxSize = arrayForAssign.maxSize;
 
    }
    return *this;
}
подправьте пож-та и подскажите, где деструктор вызывать
0
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
06.05.2013, 20:11 #34
Ага. Теперь вопрос. Второй шаблонный параметр Ex. Он намеренно не используется? Попробуйте ответить на вопрос, что лучше и почему: шаблонный параметр, задающий максимальный размер копируемого массива, или вон та чиселка в конструкторе.

Насчёт деструктора. В Array его вызывать не надо, он сам вызовется. Что он должен делать: 1) вызывать деструкторы для инициализированных элементов массива, на который указывает p; 2) вызывать operator delete [] для самого p; 3) не делать всего этого, если до этого был вызван метод get().

Деструктор в любом случае вызывается: завершилось ли копирование успешно или нет. Но идея в том, что он должен очищать память только в том случае, если копирование завершилось неуспешно (было выполнено частично). Если пользователь Ex забрал массив с помощью get(), то копирование считается выполненным успешно.

Подумайте, как Ex может эффективно хранить информацию о том, что было инициализировано, а что нет. Подсказка: учтите то, что сценарий использования у Ex только один — это оператор присваивания (ещё примерно то же стоит сделать и в конструкторе копирования).

Не по теме:

Не слушайте упоротых, которые верещат, что точка выхода из функции должна быть единственной. if (this == &arrayForAssign) return *this; в начале, а потом ещё один раз return *this; в конце — это нормально. Эффект тот же, читается субъективно понятнее и нет непонятного мегауровня вложенности.

1
Kreativ
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
06.05.2013, 20:52  [ТС] #35
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
Второй шаблонный параметр Ex. Он намеренно не используется?
я только вчера узнал про шаблоны классов ) и сделал Ex с этим параметром. Его вообще думаю нужно убрать, в классе Ex макс значение не нужно.

а над этим еще буду думать
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
Подумайте, как Ex может эффективно хранить информацию о том, что было инициализировано, а что нет.
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
Если пользователь Ex забрал массив с помощью get(), то копирование считается выполненным успешно.
0
Jupiter
06.05.2013, 21:01
  #36

Не по теме:

OhMyGodSoLong, а не проще задействовать уже готовый аллокатор?

0
OhMyGodSoLong
06.05.2013, 21:11
  #37

Не по теме:

А есть готовый? Который выделяет память под массив и инициализирует его содержимым другого массива без вызовов дефолтных конструкторов? Все эти костыли ж только ради выделенной части.

0
Jupiter
06.05.2013, 21:20
  #38

Не по теме:

std::allocator и std::uninitialized_copy решают проблему

1
OhMyGodSoLong
06.05.2013, 21:30
  #39

Не по теме:

Дайте я вас расцелую :)

0
Nick Alte
Эксперт С++
1639 / 1011 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
07.05.2013, 19:24 #40
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
специальный хитровыедуманным классом
Что за странная идея?! Чтобы безопасно скопировать массив, достаточно просто перехватывать исключение в операции копирования и удалить уже созданные элементы в обратном порядке:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
size_t i = 0;
try {
    for(; i < size; ++i)
        new(newArray + i) T(srcArray[i]);
} catch (...) {
    for(; i > 0;)
    {
        --i;
        newArray[i].~T();
    }
    deallocate(newArray);
    throw;
}
0
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
07.05.2013, 20:45 #41
Естессно это работает. Просто я не люблю, когда кишки наружу.
0
Nick Alte
Эксперт С++
1639 / 1011 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
07.05.2013, 23:31 #42
Все эти кишки надёжно упрятаны в сам Array, как и должно быть. Вводить дополнительный класс только для того, чтобы спрятать именно эти "кишки", делать его настолько многословным (да ещё, глядишь, и что-то другое упрятывать в другой класс) - over-engineering.
0
Kreativ
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
08.05.2013, 18:04  [ТС] #43
я не знаю как эффективно хранить информацию, думал всякие списки, массивы, но не то, вы дали подсказку, что это как то связано с оператором = , думал мб там проверять элементы и отправлять только те которые проиниц., но тоже не то
0
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
08.05.2013, 21:25 #44
Цитата Сообщение от Kreativ Посмотреть сообщение
я не знаю как эффективно хранить информацию, думал всякие списки, массивы, но не то, вы дали подсказку, что это как то связано с оператором = , думал мб там проверять элементы и отправлять только те которые проиниц., но тоже не то
Время сворачивать балаган. Правильный ответ: инициализировать массив строго последовательно слева направо. Тогда достаточно хранить количество проинициализированных элементов, чтобы быстро и точно узнать, что в массиве было проинициализировано, а что нет. В фрагменте кода Nick Alte этой штуке соответствует счётчик i.
Цитата Сообщение от Nick Alte Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
size_t i = 0;
try {
    for(; i < size; ++i)
        new(newArray + i) T(srcArray[i]);
} catch (...) {
    for(; i > 0;)
    {
        --i;
        newArray[i].~T();
    }
    deallocate(newArray);
    throw;
}
1
Kreativ
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
09.05.2013, 13:30  [ТС] #45
Когда я в main()'е использую оператор=, то при завершении, когда уже вызываются деструкторы, вылетает ошибка. Пошагово прогонял, вызывается деструктор Array, но дальше, в деструктор моего созданного класса, он даже не заходит.
C++
1
2
3
4
5
6
7
int main() {
Array<Complex<int>, 4> obj2(3), obj(3);
    cin >> obj;
    cout << endl << obj;
    obj2 = obj;
return 0;
}
Конструктор:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class T, size_t size>
Array<T, size> :: Array(const Array<T, size> &arrayForCopying) {
        bool label = true;
        Ex<T, 5> obj(arrayForCopying.currentSize);
 
        for (size_t i = 0; i < arrayForCopying.currentSize; i++) 
            if (obj.init(arrayForCopying.aPtr[i], i) == 0)
                label = false;
        
        if (label) {
            aPtr = obj.get();
            currentSize = arrayForCopying.currentSize;
            maxSize = arrayForCopying.maxSize;
        }
}
оператор =
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <class T, size_t size>
Array<T, size> & Array<T, size> :: operator = (const Array<T, size> &arrayForAssign) {
    if (this != &arrayForAssign) {
        bool label = true;
        Ex<T, 5> obj(arrayForAssign.currentSize);
 
        for (size_t i = 0; i < arrayForAssign.currentSize; i++) 
            if (obj.init(arrayForAssign.aPtr[i], i) == 0)
                label = false;
        
        if (label) {
            delete [] aPtr;
            aPtr = obj.get();
            currentSize = arrayForAssign.currentSize;
            maxSize = arrayForAssign.maxSize;
        }
        return *this;
    }
    return *this;
}
Деструктор Array:
C++
1
2
3
4
template <class T, size_t size>
Array<T, size> :: ~Array() {
    delete []  aPtr;
}
Метод init
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class T>
int Ex<T> :: init(const T &elem, size_t n) {
    try {
        new (p + n) T(elem);
        return 1;
    }
    catch(...) {
        for (int i = n; i >= 0; i++) {
            p[i].~T();
        }
        operator delete[](p);
        
        return 0;
    }
}
и деструктор класса Ex
C++
1
2
3
4
template <class T>
Ex<T> :: ~Ex() {
    //delete [] p;
}
Добавлено через 1 час 18 минут
нашел свои ошибки, исправил, вроде все работает, но мб что-то нужно будет исправить:
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
template <class T, size_t size>
Array<T, size> :: Array(size_t length) {
    maxSize = size;
    currentSize = length < size ? length : maxSize;
    aPtr = reinterpret_cast<T*>(operator new[](length * sizeof(T)) );
}
template <class T, size_t size>
Array<T, size> :: Array(const Array<T, size> &arrayForCopying) {
    bool label = true;
    Ex<T, 5> obj(arrayForCopying.currentSize);
 
    for (size_t i = 0; i < arrayForCopying.currentSize; i++) 
        if (obj.init(arrayForCopying.aPtr[i], i) == 0)
            label = false;
        
    if (label) {
        aPtr = obj.get();
        currentSize = arrayForCopying.currentSize;
        maxSize = arrayForCopying.maxSize;
    }
}
template <class T, size_t size>
Array<T, size> :: ~Array() {
    for (int i = (currentSize - 1); i >= 0; i--) {
        aPtr[i].~T();
    }
    operator delete[] (aPtr);
}
template <class T, size_t size>
Array<T, size> & Array<T, size> :: operator = (const Array<T, size> &arrayForAssign) {
    if (this != &arrayForAssign) {
        bool label = true;
        Ex<T> obj(arrayForAssign.currentSize);
 
        for (size_t i = 0; i < arrayForAssign.currentSize; i++) 
            if (obj.init(arrayForAssign.aPtr[i], i) == 0)
                label = false;
        
        if (label) {
            int i = arrayForAssign.currentSize - 1;
            for (; i >= 0; i--) {
                aPtr[i].~T();
            }
            operator delete[] (aPtr);
            aPtr = obj.get();
            currentSize = arrayForAssign.currentSize;
            maxSize = arrayForAssign.maxSize;
        }
    }
    return *this;
}
0
09.05.2013, 13:30
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.05.2013, 13:30
Привет! Вот еще темы с ответами:

Выход за границы. как исправить??? - C++
Суто проги в том, чтобы из 2х массивов создать третий элементами которого я вляются совпавшие элементы первых 2х Например: 1 2 3 4 5 ...

Почему происходит выход за границы? - C++
2 игрока берут из своих колод по 1-й карте. Т.е. достают элемент дека из начала дека. Так происходит, пока колода одного из игроков не...

Непонятная ошибка (выход за границы вектора) - C++
Имеется следующий код // header.h #include &lt;windows.h&gt; #include &lt;vector&gt; ...

Не удаётся устранить необработанное исключение(выход за границы вектора) - C++
Помогите пожалуйста, по мне так всё правильно и аналогичная функция в другом месте работает, но всё равно выдает ошибку void...


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

Или воспользуйтесь поиском по форуму:
45
Ответ Создать тему
Опции темы

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