Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/125: Рейтинг темы: голосов - 125, средняя оценка - 4.60
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202

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

05.05.2013, 12:39. Показов 25781. Ответов 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
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.05.2013, 12:39
Ответы с готовыми решениями:

Выход за границы массива
#include &lt;iostream&gt; #include &lt;algorithm&gt; using namespace std; void umnozh(int** arr, int n,int strings, int cols) { for (int i =...

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

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

44
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 20:20  [ТС]
Студворк — интернет-сервис помощи студентам
задание просто такое, получил такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 = ptr;
            return *this;
        }
        catch(...) {
            delete [] ptr;   
        }  
    }
    return *this;
}
все ли правильно?
я не понял только где у меня
Цитата Сообщение от Nick Alte Посмотреть сообщение
создаётся сразу инициализированный массив со значениями по умолчанию.
0
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
05.05.2013, 20:23
Цитата Сообщение от Kreativ Посмотреть сообщение
я не понял только где у меня
строка 4
1
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 20:27  [ТС]
я же просто выделил память и ничего больше
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
05.05.2013, 20:28
Так new для каждого элемента вызывает конструктор по умолчанию (для классов).
1
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 20:29  [ТС]
точно, подскажите тогда как мне переделать
0
~ Эврика! ~
 Аватар для OhMyGodSoLong
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
05.05.2013, 21:40
Цитата Сообщение от Kreativ Посмотреть сообщение
точно, подскажите тогда как мне переделать
Никак. Забейте. Вам это не нужно.

Как сделать exception-safe копирование динамического массива без вызова конструкторов по умолчанию я уже говорил: специальный хитровыедуманным классом. Там строк на 50 кода.
1
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
05.05.2013, 21:54  [ТС]
это про scoped_partially_initialized_array ?
0
~ Эврика! ~
 Аватар для OhMyGodSoLong
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
05.05.2013, 22:02
Ага. У него:
  • конструктор, принимающий количество будущих элементов массива и выделяющий кусок сырой памяти;
  • метод init(const T&), инициализирующий следующий элемент;
  • метод get() отдающий готовый кусок памяти с инициализированными элементами;
  • деструктор, дёргающий деструкторы для всего, что было инициализировано, и освобождающий сырую память (всё это при условии, что метод get() ранее не был вызван).
Примитивные выделяторы памяти зовутся void* operator new[](size_t n) и void operator delete[](void *). Первый принимает количество байт и возвращает кусок, второй принимает кусок и освобождает его. Для ручного вызова конструкторов копирования гуглите placement new. Как вызвать деструктор, думаю, догадаетесь.
1
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
06.05.2013, 00:05  [ТС]
большое спасибо, сейчас начну делать

Добавлено через 2 часа 0 минут
я пишу класс по пунктам, которые вы перечислили, но кажется я не понял всю логику.
в метод init я буду отправлять по одному элементу, который нужно скопировать, в этом методе будет происходить инициализация внутреннего указателя класса, я так понял, что здесь нужно вызывать констр. копирования вручную?
после того как все элементы будут отправлены в метод init, методом get я должен буду получить все скопированные значения(из внутр. указ.)?
еще нужно будет перегрузить операторы new, delete и в конструкторе память выделять как обычно
p = new T[size];
а где и когда вызывать вручную деструкторы?
0
~ Эврика! ~
 Аватар для OhMyGodSoLong
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
06.05.2013, 00:41
Вот что за петух вас клюнул? У вас не продакшн-левел библиотека массивов, подобные извращения тут ни к чему.

Эта штука нужна для exception-safety при копировании массива. Её задача: или выдать вам в конце концов указатель на массив из корректно скопированных элементов, или аккуратно удалить весь мусор в случае выброса исключения в процессе копирования. Любого исключения, будь-то память не выделилась или конструктор копирования облажался.

Если бы вам кое-кто не подкинул мысль, что конструктор по умолчанию может и не существовать, то достаточно было бы примитивного варианта в три строки со временным массивом.

Перегружать ничего не надо. Это именно что такие функции, которые именно так и вызываются:
C++
1
2
3
T *ptr = reinterpret_cast<T*>(operator new[](N * sizeof(*ptr)));
///
operator delete[](ptr);
malloc() и free(), считайте.

Конструктор копирования с помощью placement new вызвается в том init().

get() возвращает тот указатель на массив, что вернул operator new[](), и в котором проводил инициализацию init(). После этого данный объект забывает этот указатель. Он передал ему тому, кто вызвал get().

Деструкторы вызываются в деструкторе этого класса. Вызывать их надо только для того, что было проинициализировано (надо помнить, какой кусок массива был проинициализирован, а какой — нет). И только в том случае, если get() не был вызван до этого.

Ещё раз говорю: забейте. Если вы не знаете, зачем это надо, то оно вам не надо. YAGNI.
1
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
06.05.2013, 01:00  [ТС]
теперь я обязательно должен это сделать )
0
~ Эврика! ~
 Аватар для OhMyGodSoLong
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
06.05.2013, 01:14
Как сделаете, вперёд читать про RAII и умные указатели Так называется общий к вот таким штукам.
0
2 / 2 / 0
Регистрация: 22.09.2012
Сообщений: 202
06.05.2013, 18:48  [ТС]
наброски класса сделал, только проблема с деструктором, вот сам класс:
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
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
06.05.2013, 20:11
Ага. Теперь вопрос. Второй шаблонный параметр Ex. Он намеренно не используется? Попробуйте ответить на вопрос, что лучше и почему: шаблонный параметр, задающий максимальный размер копируемого массива, или вон та чиселка в конструкторе.

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

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

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

Не по теме:

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

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

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

Не по теме:

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

0
06.05.2013, 21:11

Не по теме:

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

0
06.05.2013, 21:20

Не по теме:

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

1
06.05.2013, 21:30

Не по теме:

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

0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
07.05.2013, 19:24
Цитата Сообщение от 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.05.2013, 19:24

Присутствует ли в программе выход за границы массива
Здравствуйте. Задача. Дано 3 числа (a, b, c) и массив. Нужно проверить есть ли в массиве значения a, b, c подряд. Решение bool...

Выход за границы массива
Выход за пределы массива, как исправить, подобная вещь и в C# Sub pol(ByRef a() As Integer, ByRef b() As Integer, ByVal n As...

Выход за границы массива
Написал код static void Main(string args) { int n, m, i = 0; string text =...

Выход за границы массива
Найдите пожалустай в чем ошибка? ошибка времени выполнения индекс находится за границы массива program master4; Var a: array of...

Выход за границы массива
Помогите реализовать идею. Есть число, например, 001.002.003. Мне надо прочитать число до первой точки, и отправить в метод, потом до...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Установка нескольких штампов электронной подписи в строго определенных местах файла docx
ВладимирСамохин 19.07.2026
(В!) Работа с Электронной подписью - это неотъемлемая часть современного документооборота. Но что делать, если нужно поставить несколько штампов электронной подписи в строго определенных местах. . .
сукцессия 35. Научная статья о проделанной работе
anaschu 19.07.2026
Написал в формате латекс и пдф
Вангую, что это не пройдёт модерацию, и на неделе я запущу свой сервер.
Hrethgir 19.07.2026
Эта публикация сейчас в песочнице и ждёт приглашения. https:/ / habr. com/ ru/ sandbox/ 295048/ начало и оглавление - Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование. . .
сукцессия 33. открытые вопросы от клауде
anaschu 19.07.2026
"Что накопилось за эту часть А — тринадцать правок, из которых шесть пришли из ваших вопросов и каждая оказалась реальной ошибкой, а не калибровкой: односторонний симбиоз, отсутствующий листопад,. . .
32 сукцессия
anaschu 19.07.2026
сукцессия 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не «подкручивает» сходимость —. . .
сукцессия 31: модель микоризы - это модель ещё нескольких явлений, социальных и экономических
anaschu 18.07.2026
Теория «Всего»: апдейт v1. 1. 2 — 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не. . .
сукцессия 30. Массив проверяющих друг друга моделей
anaschu 18.07.2026
Архитектура сети взаимопроверяющих моделей микоризной сукцессии (v2. 0) Развитие тензорного ОДУ-ядра и создание кросс-платформенного калибровочного полигона Уважаемые коллеги! В продолжение. . .
Грибы - это женщины, деревья - это мужчины. Анти инь янь для союза мужчины и женщины.
anaschu 18.07.2026
ГЛАВНЫЙ НАУЧНО-ФИЛОСОФСКИЙ ВЫВОД: Сексуально-Репродуктивный Капитализм против Государства Моногамии Коллеги, мы вышли на финишную прямую 20-мерного ОДУ-моделирования вековой сукцессии (ветка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru