Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Глава 9. Динамическое выделение памяти
Динамическое выделение памяти Создание и поддержание динамических структур данных требует динамического распределения памяти: возможности в процессе выполнения программы изменения области памяти для хранения новых узлов и освобождения ресурсов памяти, в которых уже нет необходимости. Пределы динамического выделения памяти ограничены только объемом доступной физической или виртуальной памяти в системах с виртуальной памятью. Операции new и delete – основные для работы с динамической памятью. Операция new принимает в качестве аргумента тип динамического размещения объекта и возвращает указатель на объект этого типа. Пример 1 Node *newptr = new Node[10]; // выделяет в памяти sizeof(Node) байтов и сохраняет указатель на область памяти указателем Ptr. Число 10 – число размещенных объектов данных. Пример 2 Main () { int * p = new int; cout << "sizeof(int) = " << sizeof(int) "\n"; } Для освобождения памяти используется оператор delete. Указатель newptr не удаляется, а исчезает область памяти, на которую указывает newptr. Пример 3 delete[] newptr; Пример 4 main() { char *p = new char[100]; char *q = new char[100]; delete p; delete q; } Типичные ошибки: · может быть ссылка на область памяти, которая уже была освобождена · оператором delete освобождать память, которая не была выделена new · не осуществляется возвращение динамически выделенной памяти, когда эта память уже не требуется. Это может явиться причиной переполнения памяти (утечка памяти) · предположение о том, что размер объекта класса является простой суммой объектов его элементов данных. Это не так по причине различных машинно-зависимых требований по выравниванию границ области памяти. · необходимо проверять, не вернула функция new нулевой указатель Пример 5 /* распределить память под 1-мерный массив указателей на беззнаковые целые размером degree по адресу tab используя оператор new */ tab=new unsigned *(degree); /* под каждый указатель полученного массива указателей распределить одномерный массив беззнаковых целых из degree элементов, используя оператор new в цикле */ for (int i=0; i<degree;i++) tab[i]=new unsigned(degree); /* освободить память, распределенную под degree одномерных массивов беззнаковых целых (из degree элементов каждый) по адресам от tab[0] до tab[degree-1] */ for (int i=0; i<degree; i++)
delete [degree](tab[i]); /* освободить память, распределенную под 1-мерный массив указателей на беззнаковые целые, состоящий из degree указателей по адресу tab */ delete [degree]tab;
Глава 10. Перегрузка операций Перегрузка операций Функция-оператор (операторная функция, функциональная операция) может быть определена как внутри описания класса, так и вне его. Различают два вида операторных функций: · простую (определяется вне класса, может быть одноместной или двухместной) · компонентную (определяется в классе. У нее первый аргумент представляет собой объект класса, заданный неявно. Она может быть одноместной – не имеет явных аргументов, либо двухместной – с одним аргументом)
<тип результата> - тип возвращаемого значения (имеет тот же тип, что и класс, но возможен и иной тип значения). Следует помнить, что нельзя перегружать следующие операторы:.::.*? sizeof и операторы препроцессора # и ## Перегрузка операций подчинена следующим правилам: · при перегрузке операций сохраняется количество аргументов, приоритеты операций и правила ассоциации, используемые в стандартных типах данных · для стандартных типов данных переопределить операции нельзя · функциональные операции не могут иметь аргументов по умолчанию · функциональные операции наследуются (кроме операции присваивания =) · функциональные операции не могут определяться как static Функциональную операцию можно определить тремя способами: · как метод класса · как дружественную функцию · как обычную функцию Если операторная функция определяется вторым и третьим способами, то она должна принимать хотя бы один аргумент, имеющий тип класса, либо указатель или ссылку на класс. Особый случай операторной функции: когда первый параметр имеет стандартный тип. В этом случае она не определяется как метод класса.
Формы вызова операторной функции:
Перегрузка унарных операций Унарная операторная функция может быть определена как внутри, так и вне класса. Унарная функциональная операция, определенная внутри класса, должна быть представлена с помощью нестатического метода. При этом операндом является вызывающий её объект. Пример 1 Class monstr { monstr &operator ++() { ++health; return *this; } }; monstr Vasia; cout<<(++Vasia).get_health(); Если унарная операция определена вне класса, она должна иметь один параметр - типа класса Пример 2 Class monstr { friend monstr &operator ++(monstr &M); }; monstr &operator ++ (monstr &M) { ++M.health; return M; } Если не описывать функцию внутри класса как дружественную функцию, нужно учитывать доступность полей. В данном примере поле health не доступно извне, т.к. описано как private. Для его изменения следует использовать специальные методы. Введем в класс monstr специальный метод change_health, который будет позволять менять значение health: Пример 3 void change_health(int he) {health =he;} При вводе этого метода можно пере+гружать оператор инкрементации с помощью обычной функции, описанной вне класса: Пример 4 monstr &operator ++ (monstr &M) { int h=M.get_health(); h++; M.change_health(h); return M; } В случае использования оператора постфиксного инкремента и декремента дадим им первый параметр типа int. Он используется для того, чтобы отличить их от префиксной формы. Пример 5 const monstr operator ++ (int) { monstr M(*this); health++; /* Лучше ++(*this); */ return M; } monstr Vasia; cout << (Vasia++).get_health();
|
||||||||||||||||||||||
Последнее изменение этой страницы: 2021-07-18; просмотров: 92; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.226.181.45 (0.014 с.) |