Пам'яттю (new, delete)

Як відомо, у програмах ANSI C використовуються функції malloc() та free() разом з подібними до них для виділення та звільнення пам'яті в купі. У С++ використовуються операції new та delete. У більшості версій С++ ці операції скрито реалізуються викликами функцій malloc() та free(). Тому може скластись враження, що немає принципової різниці в керуванні пам'яттю в мовах С та С++. Проте це не так. Той факт, що new та delete є операціями, дає можливість у С++ їх перевантажити. Це дозволяє створювати гнучкішу систему роботи з пам'яттю для об'єктів. Наприклад:

#pragma warn - aus

//виключаються повідомлення компілятора про те, що

//визначаються та не використовуються змінні

char buf [512];

int index;

class MyNew {

int x;

public:

MyNew(){};

void*operator new(size_t)

{

cout<<"перевантажений оператор new:\n";

if(index>512-sizeof(MyNew)) {

cout<<"недостатньо пам’яті\n";

return 0;}

else{

int k=index;

index+=sizeof(MyNew);

cout<<"\n"<<index<<"\n";

return &buf[k];}

}

};

Main()

{

MyNew*b=new MyNew;

MyNew*b1=new MyNew;

}

Результати роботи програми:

перевантажений оператор new:

перевантажений оператор new:

Якщо в main()- функції дописати цикл

for(int i=0;i<127;i++)

MyNew*b2=new MyNew;,

то отримаємо повідомлення: недостатньо пам’яті.

Якщо ж оголосити масив елементів типу MyNew

Mynew*mas=new MyNew[20];,

то викликатиметься стандартна операція new.

Зазначимо, що в С++ версії 4.5 вимагається наявність параметра типу size_t у перевантаженому операторі new. Тому в наведеному вище прикладі записується параметр size_t в оголошенні:

void*operator new(size_t);

Аналогічно перевантажується оператор delete. Прототип функції перевантаження оператора delete повинен мати вигляд void operator delete(void*p);, де р посилається на об’єкт, що знищується. Як альтернативу можемо оголосити функцію, наприклад, так:

void operator delete(void*p,int size);

Другим аргументом тут виступає кількість байтів в об'єкті, що знищується.

Перевантаження операції присвоювання

Повернемось до проблеми, яка виникає при присвоюванні об'єктів. Вона легко розв'язується за допомогою перевантаження цієї операції:

class intarray{

int size;

int*ar;

public:

Intarray(int size)

{ar=new int[size];}

void operator=(const intarray & anintarray)

{ar=new int[anintarray.size];

for(int i=0;i<size;i++)

ar[i]=anintarray.ar[i]; }

};

У main()- функції можемо написати:

Main()

{intarray a(100);

intarray b=a;}

Завдання для самостійної роботи

1. Перевантаживши операцію <та>, написати функцію сортування масиву об'єктів за деякими ознаками його полів:

а) у порядку зростання (спадання) значень одного з полів типу char, int, float чи double;

б) у порядку лексикографічної впорядкованості полів типу *char;

в) вважаючи, що клас має два поля – p1 та p2 типу double, ввести відношення часткового порядку таким чином:

a>b якщо a.p1>b.p1 або a.p1==a.p2 && a.p1>b.p2

та впорядкувати масив;

г) ввести відношення часткового порядку, аналогічне відношенню у п. в), для n елементів, вважаючи, що відповідні поля записані у вигляді масиву.

2. Протестувати приклад із класом BrandNew, дописавши конструкції, яких не вистачає для коректної роботи програми.

3. Перевантажити операцію доступу до члена класу, щоб вона повертала об'єкт. Протестувати для цього випадку приклад із класом TAnyClass.

4. Протестувати приклад із класом a_iterator.

5. Перевантажити операції new-delete для класу Complex, щоб вони обробляли вимоги для виділення пам'яті довільного обсягу.

6. С++ не перевіряє автоматично під час виконання вихід індексу за границю масиву. Розробити тип даних масив, який виконує перевірку границь.

7. Написати тип string, що має деякі специфічні властивості (лічильник звернень, перевантажені оператори +,-, зведення типу тощо).

8. Реалізувати загальний клас-ітератор списку, який здійснює операції повернення наступного, попереднього елемента та голови списку.

9. Розробити тип даних гістограма, перевантаживши операцію індексування масиву для індексації з плаваючими аргументами.

10. Розробити двозв'язний список, реалізація якого використовує лише один зв'язаний покажчик. Включити в розробку ітератор, який може проходити список у будь-якому напрямку.

11. Розробити тип "розумного" покажчика, який гарантує вказування лише на вільну пам'ять.


ШАБЛОНИ С++

Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного

Аналогічно тому, як клас є схематичним описом побудови об'єкта, шаблон є схематичним описом побудови функцій i класів. Шаблони дозволяють задавати довільно узагальнені типи, визначення класів і функцій. Ці визначення можуть служити компілятору основою для класів і функцій, що створюються для конкретного типу даних. Як наслідок, шаблони є ефективним способом реалізації процедур, які зазвичай переписуються багато разів для даних різних типів.

Шаблони С++ часто називають параметризованими типами. Вони дозволяють компілювати нові класи чи функції, задаючи типи як параметри.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: