Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 37, средняя оценка - 4.68
Kreativ
2 / 2 / 6
Регистрация: 22.09.2012
Сообщений: 202
#1

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

05.05.2013, 12:39. Просмотров 6509. Ответов 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++):

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

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

Как вызвать исключение «выход за границы массива»?
Как вызвать исключение «выход за границы массива»? То есть, чтобы ввели массив...

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

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

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

44
Кудаив
409 / 408 / 72
Регистрация: 27.05.2012
Сообщений: 1,168
Завершенные тесты: 2
05.05.2013, 12:45 #2
C++
1
2
3
4
5
6
7
    try {
    if (index < 0 || index >= currentSize)
        throw out_of_range("Index was out of range");
    }
    catch(const out_of_range& oor) { // что тут писать чтобы поймать из throw
        cout << oor.what();
    }
1
Убежденный
Ушел с форума
Эксперт С++
15941 / 7251 / 1176
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
05.05.2013, 12:51 #3
1) Ловить исключения - это забота клиентского кода. Поэтому просто бросайте out_of_range,
try и catch здесь не нужны. Только задекларируйте в документации класса или самого метода,
что он может бросать данное исключение, чтобы для клиента это не стало сюрпризом.

2) Размеры обычно задаются типом size_t, а не int. Это общепринятая практика, к тому же
снижается количество потенциальных проблем при переносе на другую платформу (64-бита).

3) Не забудьте написать const-вариацию перегруженного оператора индексации.
1
OhMyGodSoLong
05.05.2013, 13:28
  #4

Не по теме:

Релизные версии STL не проверяют границы. /discuss

0
Kreativ
2 / 2 / 6
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 14:07  [ТС] #5
Цитата Сообщение от Убежденный Посмотреть сообщение
1) Ловить исключения - это забота клиентского кода. Поэтому просто бросайте out_of_range,
try и catch здесь не нужны. Только задекларируйте в документации класса или самого метода,
что он может бросать данное исключение, чтобы для клиента это не стало сюрпризом.
тогда придется в main'е делать try catch ? хотя можно написать функции в которых будут создаваться объекты и там уже try catch
0
Кудаив
409 / 408 / 72
Регистрация: 27.05.2012
Сообщений: 1,168
Завершенные тесты: 2
05.05.2013, 14:17 #6
Цитата Сообщение от Kreativ Посмотреть сообщение
1) Ловить исключения - это забота клиентского кода. Поэтому просто бросайте out_of_range,
try и catch здесь не нужны. Только задекларируйте в документации класса или самого метода,
что он может бросать данное исключение, чтобы для клиента это не стало сюрпризом.
это советы не для новичка, делай как тебе удобно
1
Убежденный
Ушел с форума
Эксперт С++
15941 / 7251 / 1176
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
05.05.2013, 14:21 #7
Цитата Сообщение от Kreativ Посмотреть сообщение
тогда придется в main'е делать try catch ? хотя можно написать функции в которых будут создаваться объекты и там уже try catch
Да. Выбор стратегии зависит от конкретных условий и сценариев использования класса.
Одни ошибки можно перехватить и обработать локально, после чего продолжить выполнение,
другие лучше не "прокидывать" и не маскировать, а выдать пользователю сообщение и
завершить работу программы.
1
Kreativ
2 / 2 / 6
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 16:15  [ТС] #8
у меня опять встал вопрос, я перегружаю оператор = , в нем необходимо выделить память, наверное надо поставить в try - catch, правильно ли я делаю:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <class T, size_t size>
Array<T, size> & Array<T, size> :: operator = (const Array<T, size> &arrayForAssign) {
    if (aPtr != nullptr) // нужно ли ставить проверку, если массив которому я присваиваю не инициализирован  
        delete [] aPtr;  
    currentSize = arrayForAssign.currentSize;
    maxSize = arrayForAssign.maxSize;
    try {
        aPtr = new T[currentSize]; // new сам же выбрасывает bad_alloc
        for (size_t i = 0; i < currentSize; i++) 
            aPtr[i] = arrayForAssign.aPtr[i];
    }
    catch(bad_alloc &exc) {
        cout << exc.what() << endl;
    }
    return *this;
}
где мне обрабатывать искл. внутри перегруженного оператора или нет?
0
Jupiter
Каратель
Эксперт С++
6568 / 3989 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
05.05.2013, 16:18 #9
Цитата Сообщение от Kreativ Посмотреть сообщение
где мне обрабатывать искл. внутри перегруженного оператора или нет?
нет
0
Kreativ
2 / 2 / 6
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 16:25  [ТС] #10
сделал так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template <class T, size_t size>
Array<T, size> & Array<T, size> :: operator = (const Array<T, size> &arrayForAssign) {
    if (this != &arrayForAssign) {
        if (aPtr != nullptr)
            delete [] aPtr;   
        currentSize = arrayForAssign.currentSize;
        maxSize = arrayForAssign.maxSize;
        aPtr = new T[currentSize];
        for (size_t i = 0; i < currentSize; i++) 
            aPtr[i] = arrayForAssign.aPtr[i];
    }
    return *this;
}
нужна ли проверка
C++
1
2
if (aPtr != nullptr)
            delete [] aPtr;
чтобы не очищать память пустого массива
и как быть если скажем память не выделилась, тогда мой массив останется пустым, его размеры изменятся
0
Jupiter
Каратель
Эксперт С++
6568 / 3989 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
05.05.2013, 16:26 #11
Цитата Сообщение от Kreativ Посмотреть сообщение
нужна ли проверка
нет
Цитата Сообщение от Kreativ Посмотреть сообщение
и как быть если скажем память не выделилась, тогда мой массив останется пустым, его размеры изменятся
http://ru.wikipedia.org/wiki/%D0%98%..._copy-and-swap
1
Nick Alte
Эксперт С++
1646 / 1018 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
05.05.2013, 16:39 #12
Сообщать об исключении и тем более гасить его - совершенно не операторское дело. Его задача только "подчистить" что возможно и насколько возможно в данной ситуации и передать исключение дальше. Таким образом, порядок действий такой:
а) выделить память под новый массив, исключение при этом перехватывать не надо: если возникнет ошибка, то сам объект пока что в прежнем состоянии и никакие ресурсы не утекли.
б) переписать содержимое копируемого объекта в выделенную память, перехватывая исключения. Если при копировании одного из элементов будет выброшено исключение, уже надо освобождать ресурсы: в обратном порядке уничтожить уже заполненные элементы нового массива и освободить сам массив.
в) уничтожить содержимое старого массива и освободить его, после чего заменить новым массивом. Эта операция не должна приводить к исключительным ситуациям (если тип T сделан по уму и его деструктор не выбрасывает исключений).
При таком порядке действий операция либо завершится успешно, либо будет прервана исключением, а сам объект при этом останется в том же состоянии, в котором был до начала операции (т.н. "сильная" гарантия безопасности). Утечек при возникновении исключений такой оператор тоже не создаст.
2
Kreativ
2 / 2 / 6
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 17:11  [ТС] #13
Цитата Сообщение от Nick Alte Посмотреть сообщение
Если при копировании одного из элементов будет выброшено исключение, уже надо освобождать ресурсы: в обратном порядке уничтожить уже заполненные элементы нового массива и освободить сам массив.
затем в пункте В
Цитата Сообщение от Nick Alte Посмотреть сообщение
в) уничтожить содержимое старого массива и освободить его, после чего заменить новым массивом.
а так новый массив то пуст будет если будет выброшено исключение
0
OhMyGodSoLong
~ Эврика! ~
1245 / 994 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
05.05.2013, 17:15 #14
Третий пункт не выполняется, если во втором вылетает исключение.
1
Kreativ
2 / 2 / 6
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 17:40  [ТС] #15
Посмотрите пож-та, я сделал по пунктам:
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
template <class T, size_t size>
Array<T, size> & Array<T, size> :: operator = (const Array<T, size> &arrayForAssign) {
    if (this != &arrayForAssign) {
        T *ptr = new T[arrayForAssign.currentSize]; // 1 пункт
        size_t s = arrayForAssign.currentSize;
 
        try {      // 2 пункт
            for (size_t i = 0; i < arrayForAssign.currentSize; i++) {
                ptr[i] = arrayForAssign.aPtr[i];
            }
 
            delete [] aPtr;  // 3 пункт если в копировании исключ не сгенерировалось
            currentSize = s;
            maxSize = arrayForAssign.maxSize;
            aPtr = new T[currentSize];
            for (size_t i = 0; i < currentSize; i++) 
                aPtr[i] = ptr[i];
            
        }
        catch(...) { // а что тут ловить?
            delete [] ptr;   
        }  
        return *this;
    }
    return *this;
}
Добавлено через 10 минут
перед catch забыл еще удалить ptr
0
Nick Alte
Эксперт С++
1646 / 1018 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
05.05.2013, 18:33 #16
Не совсем хорошо то, что создаётся сразу инициализированный массив со значениями по умолчанию. По-хорошему надо бы выделить "сырую" память и создавать значения непосредственно из исходных данных. При текущем положении дел Array нельзя применять для типов, не имеющих конструктора по умолчанию. Далее, при выполнении 3 пункта наступает лютый трындец: зачем-то выделяется ещё один (!) массив, куда копируются данные из временного. Что за ерунда? Надо было просто написать aPtr = ptr;
1
Kreativ
2 / 2 / 6
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 19:07  [ТС] #17
Цитата Сообщение от Nick Alte Посмотреть сообщение
Не совсем хорошо то, что создаётся сразу инициализированный массив со значениями по умолчанию.
вы имеете в виду, что в конструкторе по умолчанию создается сразу инициализированный массив?
я же здесь выделил "сырую" память и скопировал значения из массива:
C++
1
2
3
4
5
6
7
     T *ptr = new T[arrayForAssign.currentSize]; // выделил память
        size_t s = arrayForAssign.currentSize;
 
        try {      // 2 пункт
            for (size_t i = 0; i < arrayForAssign.currentSize; i++) {
                ptr[i] = arrayForAssign.aPtr[i];  скопировал во временный массив
            }
Цитата Сообщение от Nick Alte Посмотреть сообщение
при выполнении 3 пункта наступает лютый трындец: зачем-то выделяется ещё один (!) массив, куда копируются данные из временного. Что за ерунда? Надо было просто написать aPtr = ptr;
я не знаю с чего решил, что раз локальная переменная ptr, то и очистится память по заврешении оператора, моя оплошность
0
OhMyGodSoLong
~ Эврика! ~
1245 / 994 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
05.05.2013, 19:50 #18
Цитата Сообщение от Nick Alte Посмотреть сообщение
Не совсем хорошо то, что создаётся сразу инициализированный массив со значениями по умолчанию. По-хорошему надо бы выделить "сырую" память и создавать значения непосредственно из исходных данных.
О да, и писать свой scoped_partially_initialized_array!
0
Kreativ
2 / 2 / 6
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 19:54  [ТС] #19
а что значит scoped_partially_initialized_array?
0
OhMyGodSoLong
~ Эврика! ~
1245 / 994 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
05.05.2013, 20:02 #20
Это такой выдуманный класс, хранящий указатель на кусок памяти, который на самом деле является массивом, для которого частично вызваны конструкторы. И деструктор которого должен вызвать деструкторы для того, для чего вызывались ранее конструкторы, а потом освободить память того куска.
1
05.05.2013, 20:02
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.05.2013, 20:02
Привет! Вот еще темы с решениями:

Выход итератора за границы list
почему у меня падает программа, когда пытаюсь ввести отсортированные элементы...

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

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

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


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

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

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