New/delete и malloc(calloc)/free



СЕМИНАРЫ 1, 2 . Организация класса. Точки на декартовой плоскости

Теоретический материал

Конструктор — это специальная функция-член класса (метод), которая создает экземпляр класса, инициализируя его значения. Имя конструктора совпадает с именем класса.

Конструктор не возвращает значения, результат его работы – создается объект класса.

Как правило конструкторы объявляются в открытой (публичной) секции класса, поскольку деятельность конструктором заключается в создании объекта класса и производится извне класса.

Вызов конструкторов как правило производится не явно, то есть указывается

CLASS_NAME obj;

При котором создается объект obj, а скобки вызова конструктора отсутсвуют.

 

Конструктор со списком инициализации приведен в примере.

Имеются две формы инициализации полей класса при создании объектов. Во всех приведенных выше определениях конструкторов была продемонстрирована одна из этих форм, которую условно можно назвать первой. Простейший ее пример:

TString(int n) { N = n; }

Эта форма предполагает использование операции присваивания в теле конструктора. Вторая форма предусматривает использование списка инициализаторов, который размещается между списком аргументов и телом конструктора:

класс(аргументы):инициализаторы { операторы конструктора; }

Такая форма инициализации считается более эффективной.

class Point {

private:

int x;

int y;

public:

Point(int _х, int _y) : x(_x), y(_y) { }; // конструктор точки

};

 

Выделенное – список инициализации. Последовательность инициализации данные – строго как указана в списке объявления в спецификации класса. Если изменить последовательность – компилятор выдаст предупреждения.

 

Конструктор по умолчанию – конструктор не имеющий параметров. Если конструктор по умолчанию не задан явно и нет конструкторов с параметрами, то он создастся автоматически, при этом поля объекта будут инициализированы мусором.

class Point {

public:

Point(); // конструктор по умолчанию

};

 

Еще один вариант конструктора по умолчанию – конструктор, всем параметрам которого присвоены значения.

DATA(int a=0, int b=10);

 

Такой конструктор может вызываться как с аргументами

DATA Н(3, 4);

Так и без аргументов (как обычный конструктор по умолчанию:

 DATA R;

 

Существует промежуточный вариант – когда части параметром заданы значений по умолчанию, а второй части параметров требуется инициализация значений.

DATA(int а , int b=10);

Создание объекта таким конструктором будет выглядеть следующим образом

 DATA G(5);

ВАЖНО: аргументу можно задать значение по умолчанию, если он находится правее всех в списке аргументов, или если все аргументы правее него имеют значения по умолчанию.

 

В рамках одного класса может быть объявлен только один конструктор по умолчанию так как в противном случае конструкторы будут неразличимы при вызове.

Если необходимо создать массив объектов, это реализуется вызовом конструктора по умолчанию. Альтернативный вариант – конструктор с инициализированными полями.

 

Копирующий конструктор. Конструктор, который в качестве аргумента принимает другой объект того же типа — называется копирующим конструктором. В этом случае новый объект будет создан как копия уже существующего объекта. Обычно аргумент копирующего конструктора объявляется как ссылка на константу, чтобы копия никак не влияла на оригинал. Копирующий конструктор создаётся по умолчанию, если не задан явно. В поля нового объекта он копирует значения соответствующих полей объекта-аргумента.

Общий синтаксис конструктора копирования

My_Class(const My_Class&);

// здесь My_Class - это имя класса

const My_Class& - ссылка на объект этого же класса;

 

Использование спецификатора const не случайно: как известно, выражение вызова функции с параметром типа X ничем не отличается от выражения вызова функции, у которой параметром является ссылка на объект типа X. При вызове такой функции не приходится копировать объекты как параметры. Передача адреса не требует копирования объекта, а значит, при этом не будет и рекурсии.

 

Использование стандартного конструктора копирования в случае, если в классе нет полей, используемых для динамического выделения памяти, не представляет никакой особенности. Ситуация меняется, если у класса есть поля, используемые для динамического выделения памяти, как, например поле str в TString. В этом случае стандартный конструктор копирования будет напрямую присваивать значение указателя на динамическую память для одного (существующего) объекта указателю для другого (нового) объекта. В итоге два разных указателя будут адресовать одну и ту же область памяти.

Если один из этих объектов изменяет содержимое динамической памяти, то изменяется содержимое такой памяти и для второго объекта, что является неправильным (в большинстве алгоритмов обработки объектов, кроме специально предусмотренных случаев). Кроме того, если один из этих объектов является локальным в блоке, то при выходе из блока он уничтожается и занимаемая им память считается свободной для дальнейшего

30использования. Но другой объект всѐ ещѐ существует, и его память не должна считаться свободной и подвергаться изменениям.

Для предотвращения такой ситуации, если она нежелательна, нужно явно создать конструктор копирования (нестандартный), который будет не просто напрямую копировать значения полей, но и, при необходимости выделять динамическую память и копировать в новую область памяти данные из такой же памяти исходного объекта.

 

Деструкторы

Деструкторы выполняют работу, обратную той, что проделывают конструкторы. Хотя класс может иметь несколько конструкторов, но деструктор может быть только один. Синтаксис деструктора очень похож на синтаксис конструктора по умолчанию.

~CLASS_ NAME ();

 

Деструктор почти всегда вызывается неявно. Вызов деструктора происходит:

1. при выходе объекта за пределы своей области видимости: выходе программы из блока, где создавались автоматические объекты классов, при завершении программы (вызове функции exit) для глобальных и статических объектов

2.  при уничтожении динамического созданного (операцией new) объекта операцией delete.

 

Деструкторы всегда вызываются в порядке, обратном последовательности определения объектов

Если в классе нет явно созданного деструктора, то, также как и конструктор, компилятор создаѐт его автоматически, с открытым режимом доступа.

 

Типы данных Class и struct:

Они очень похожи, отличительная особенность – в структуре все поля по умолчанию открыты (public), а в классе – закрыты, то есть не доступны для внешнего обращения.

 

 

New/delete и malloc(calloc)/free

• malloc выделяет неинициализированную память. Её нужно освобождать, используя free.

• calloc делает то же, что и malloc, только выделенная память инициализируется константой (0). Освобождается с помощью free.

• new выделяет и инициализирует память, вызывая конструктор (если память выделяется под объект). Освобождается вызовом оператора delete (который, по сути, вызывает деструктор объекта).

 

Оператор malloc выделяет блок памяти. Размер блока задается в байтах. Возвращает адрес выделенного блока или ноль, если не удалось выделить память.

new и delete являются улучшенными вариантом операторов malloc и free.

new позволяет выделять память, необходимую для размещения переменной, структурной переменной или массива. Для переменной необходимо указывать тип и в случае массива - размер. new может записывать значение в созданную переменную.

В отличие от malloc, при использовании оператора new ненужно указывать количество байт памяти, которое необходимо выделить.

Следует отметить, что допустимо только совместное использование однотипных средств выделения/освобождения памяти: New/delete и malloc(calloc)/free

Варианты New/free и malloc(calloc)/delete не допустимы!

 

Компоненты пустого класса:

Таким образом, в пустом классе вида class A{}; имеются:

– стандартный конструктор;

– стандартный конструктор копирования;

– деструктор;

– стандартная перегруженная операция присваивания.

 

Дружественная функция — это функция, которая не является членом класса, но имеет доступ к членам класса, объявленным в полях private или protected. Дружественная функция может располагаться в любом поле класса – private, public или protected. Она при любых обстоятельствах будет иметь доступ к private-элементам класса и, даже если она сама находится в поле private (как в нашем примере), к ней можно будет обратиться вне класса, не используя специальных методов.

Их можно объявлять и определять в любом поле класса, будь то private, public или protected,

Объявление дружественных функций отличается от объявления методов класса тем, что перед типом возвращаемого функцией значения используется зарезервированное слово friend.

Обратите внимание, что в виде параметра мы передаем этим функциям ссылку на объект нашего класса.

Дружественная функция не принадлежит классу, не является его компонентом, поэтому при ее описании не используется оператор ::

Дружественные функции широко используются когда одну функцию необходимо использовать для нескольких классов.

 


Дата добавления: 2021-06-02; просмотров: 79; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!