67312

Перевантаження операторів new і delete

Лекция

Информатика, кибернетика и программирование

Розробник може керувати виділенням пам’яті, перевантажуючи оператори new і delete. Такі оператори переважно перевантажуються як методи класу. Проте дозволено перевантаження і як дружніх функцій Операторні функції операторів new і delete в обидвох випадках мають вид...

Украинкский

2014-09-07

201.5 KB

1 чел.

Лекція № 14

Тема: Перевантаження операторів new і delete

План

  1.  Перевантаження операторів new і delete
  2.  Перевантаження операторів new тa delete як методів  класу
  3.  Перевантаження операторів new тa delete як дружніх функцій
  4.  Перевантаження операторів new і delete при роботі з масивами
  5.  Оператор new із розміщенням

  1.  Перевантаження операторів new і delete

  •  Розробник може керувати виділенням пам’яті, перевантажуючи оператори new і delete. Такі оператори переважно перевантажуються як методи класу. Проте дозволено перевантаження і як дружніх функцій
  •  Операторні функції операторів new і delete в обидвох випадках мають вид
  1.  void* operator new (size_t size);
  2.  void operator delete (void*);
  •  Операторна функція new виділяє size байт і повертає адрес виділеної пам’яті. Конструктори та деструктори об’єктів при цьому викликаються автоматично.
  •  Тип size_t є псевдоіменем цілочисельного типу.

  1.  Перевантаження операторів new тa delete як методів  класу

  •  Перш за все відзначимо два дуже важливих моменти для перевантажених як методи класу операторів new і delete (а також іх різновидів):
  •  такі оператори вважається статичними, навіть без явного оголошення. При цьому вони не отримують вказівника this;
  •  такі оператори будуть використовуватись при створення динамічних змінних лише для копій даного класу. При цьому для виділення пам’яті під змінні інших типів не будуть заміщуватись стандартні оператори.
  •  Розглянемо програму, в якій оператор new реалізовує виділення пам’яті через функцію malloc(). Як відомо одночасне використання механізмів розподілу та звільнення пам’яті, які передбачені в мовах С та С++, тобто використання пар new - free() та malloc() - delete , може привести до непередбачуваних результатів. А тому наведена програма несе певний зміст, який полягає в узгодженні різних механізмів виділення пам’яті.

  1.  Перевантаження операторів new тa delete як дружніх функцій

  •  Оператори new  і delete  можуть перевантажуватись як дружні функціі. При цьому перевантажуються вбудовані оператори.  Це означає, що при виділення пам’яті під змінні іншого (відмінного від даного класу) також буде викликатись перевантажений оператор new  чи delete.
  •  Треба пам’ятати, що синтаксично оператор new повинен приймати лише один параметр типу size_t

  1.  Перевантаження операторів new і delete при роботі з масивами

При роботі з масивами треба переванжувати оператори new[] і delete[] керуючись, тими ж правилами як і у випадку new i delete. Перевантажувати ці оператори  можна як методи класу, так і як дружні функції.

#include <iostream>

class A

{

public:

int i;

A() {  i = 0; mes();}

A(int i) {  this->i = i; mes();}

void mes(){ std::cout <<" Constructor A" <<endl;}

~A() {  std::cout<<" Destructor A"<< endl;}

friend void* operator new (size_t t,int x,int y);

friend void* operator new (size_t t);

friend void* operator new [] (size_t t);

friend void operator delete[](void*);

friend void operator delete(void*);

};

void* operator new (size_t t, int x, int y)  //N1

{

std::cout<<"Operator new (size_t t, int x,int y)"<<endl;   return malloc(x*y);

}

void* operator new (size_t t)   //N2

{

std::cout<<"Operator new (size_t t)" << endl;

return malloc(t);

}

void* operator new [] (size_t t)   //N3

{

std::cout<<"Operator new [] (size_t t)"<<endl;

return malloc(t);

}

void operator delete (void* p)   //D1

{

std::cout <<"Operator delete (void* p)"<<endl;

free(p);

}

void operator delete [] (void* p)  //D2

{

std::cout <<"Operator delete [] (void* p)"<<endl;

free(p);

}

void main()

{

char mem [sizeof(A)];

void *p = mem;

A * a  = new(p) A(1);  // оператор N2

std::cout<<"a->i="<<a->i<<endl;

delete a;    // оператор D1

std::cout<<"----------------------"<<endl;

A * a2  = new(10,10) A(2); // оператор N1

std::cout<<"a2->i="<<a2->i<<endl;

delete a2;    // оператор D1

std::cout<<"----------------------"<<endl;

A * a3  = new A[5];  // оператор N3

std::cout<<"a3->i="<<a3->i<<endl;

delete [] a3;   // оператор D2

std::cout<<"----------------------"<<endl;

int * p2  = new int[6];  // оператор N3

std::cout<<"Massive is created"<<endl;

delete [] p2;   // оператор D2

}

  1.  Оператор new із розміщенням

Оператор new  має особливу форму перевантаження, яка називається синтаксисом розміщення. Вона дозволяє створювати об’єкт, розміщуючи його в комірці пам’яті із заданою адресою.

В цьому випадку треба явно викликати деструктор класу

    Оскільки new і delete – оператори, то їх також можна перевизначати. . Це доводиться робити, якщо виникає необхідність створити особливий механізм розподілу пам'яті. Наприклад, можна створити процедуру виділення області пам'яті, яка, якщо область множини виявиться вичерпаною, автоматично починає використовувати дисковий файл як віртуальну пам'ять. У будь-якому випадку реалізація перевантаження цих операторів є не складнішою за перевантаження будь-яких інших.

   Нижче наведено схему функцій, які перевантажують оператори new і delete.

// Виділення області пам'яті для об'єкта

void *operator new(size_t size)

{

/* У разі неможливості виділити пам'ять генерується виняток

типу bad_alloc. Конструктор викликається автоматично. */

return pointer_to_memory;

}

// Видалення об'єкта.

void operator delete(void *p)

{

/* Звільняється область пам'яті, яка адресується покажчиком p.

Деструктор викликається автоматично. */

}

void * - покажчик на область пам'яті, виділювану під об'єкт, size - розмір об'єкта в

байтах, size_t - тип розмірності області пам'яті, int чи long.

   Тип size_t спеціально визначено, щоб забезпечити зберігання розміру максимально можливої області пам'яті, яку можна виділити для об'єкта. Параметр size визначає кількість байтів пам'яті, потрібної для зберігання об'єкта, для якого виділяється пам'ять. Іншими словами, це об'єм пам'яті, який повинна виділити Ваша версія оператора new. Операторна функція new повинна повертати показник на пам'ять, що виділяється нею, або генерувати винятки типу bad_alloc у випадку виникнення помилки. Окрім цих обмежень, операторна функція new може виконувати будь-які потрібні дії. Під час виділення області пам'яті для об'єкта за допомогою оператора new (його початкової форми або Вашої власної) автоматично викликається конструктор об'єкта.

   Функція delete отримує показник на область пам'яті, яку необхідно звільнити. Потім вона повинна повернути цю область пам'яті системі. Під час видалення об'єкта автоматично викликається його деструктор.

   Щоб виділити пам'ять для масиву об'єктів, а потім звільнити її, необхідно використовувати такі формати операторів new і delete.

// Виділення області пам'яті для масиву об'єктів

void *operator new[](size_t size)

{

/* У разі неможливості виділити пам'ять генерується виняток

типу bad_alloc. Кожен конструктор викликається автоматично. */

return pointer_to_memory;

}

// Видалення масиву об'єктів.

void operator delete[](void *p)

{

/* Звільняється область пам'яті, яка адресується покажчиком p.

При цьому автоматично викликається деструктор для

кожного елемента масиву. */

}

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

    Оператори new і delete, як правило, перевантажуються відносно класу. Заради простоти у наведеному нижче прикладі використовується не нова схема розподілу пам'яті, а перевантажені функції new і delete, які просто викликають С-орієнтовані функції виділення області пам'яті malloc() і free(). У своєму власному додатку Ви можете реалізувати будь-який метод виділення області пам'яті.

    Щоб перевантажити оператори new і delete для конкретного класу, достатньо зробити ці перевантажені операторні функції членами цього класу. У наведеному нижче прикладі коду програми оператори new і delete перевантажуються для класу kooClass. Це перевантаження дає змогу виділити пам'ять для об'єктів і масивів об'єктів, а потім звільнити її.

Приклад. Демонстрація механізму перевантаження операторів new і delete

#include <iostream>             // Для потокового введення-виведення

#include <new>                 // Для перевизначення операторів new і delete

#include <cstdlib>             // Для використання бібліотечних функцій

using namespace std;            // Використання стандартного простору імен

class kooClass

{

int x, y, z;             // Тривимірні координати

    public:

kooClass() { x = y = z = 0; cout << "Створення об'єкта 0, 0, 0" << endl; }

kooClass(int c, int d, int f)    {  x = c; y = d; z = f;

                                                 cout << "Створення об'єкта " << c << ", ";

                                                 cout << d << ", " << f << endl; }

~kooClass()     { cout << "Руйнування об'єкта" << endl; }

void *operator new(size_t size);

void *operator new[](size_t size);

void operator delete(void *p);

void operator delete[](void *p);

void showB(char *s);

};

    // Перевантаження оператора new для класу kooClass.

void *kooClass::operator new(size_t size)

{      void *p;

      cout << "Виділення області пам'яті для об'єкта класу kooClass" << endl;

      p = malloc(size);

             // Генерування винятку у разі невдалого виділення області пам'яті.

      if(!p)

         {    bad_alloc ba;

              throw ba;

         }

      return p;

}

    // Перевантаження оператора new для масиву об'єктів типу kooClass.

void *kooClass::operator new[](size_t size)

{     void *p;

     cout << "Виділення області пам'яті для масиву kooClass-oб'єктів" << endl;

          // Генерування винятку при невдачі.

     p = malloc(size);

     if(!p)

        { bad_allос ba;

         throw ba;

        }

    return p;

}

    // Перевантаження оператора delete для класу kooClass.

void kooClass::operator delete(void *p)

{        cout << "Видалення об'єкта класу kooClass" << endl;

        free(p);

}

   // Перевантаження оператора delete для масиву об'єктів типу kooClass.

void kooClass::operator delete[](void *p)

{       cout << "Видалення масиву об'єктів типу kooClass" << endl;

       free(p);

}

    // Відображення тривимірних координат x, y, z.

void kooClass::showB(char *s)

{      cout << "Координати об'єкта <" << s << ">: ";

      cout << "x= " << x << ", y= " << y << ", z= " << z << endl;

}

int main()

{     kooClass *p1, *p2;

     try

       {   p1 = new kooClass[3];                  // Виділення області пам'яті для масиву

           р2 = new kooClass(5, 6, 7);          // Виділення області пам'яті для об'єкта

       }

    catch(bad_alloc ba)

       {   cout << "Помилка під час виділення області пам'яті" << endl;

            return 1;

       }

    p1[1].showB("Базовий клас: ");

    p2->showB("Базовий клас: ");

    delete [] p1;          // Видалення масиву

    delete p2;             // Видалення об'єкта

    getch(); return 0;

}

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

Виділення області пам'яті для масиву kooClass-oб'єктів.

Створення об'єкта 0, 0, 0

Створення об'єкта 0, 0, 0

Створення об'єкта 0, 0, 0

Виділення області пам'яті для об'єкта класу kooClass.

Створення об'єкта 5, 6, 7

0, 0, 0

5, 6, 7

Руйнування об'єкта

Руйнування об'єкта

Руйнування об'єкта

Видалення масиву об'єктів типу kooClass.

Руйнування об'єкта

Видалення об'єкта класу kooClass.

    Перші три повідомлення Створення об'єкта 0, 0, 0 видані конструктором класу kooClass (який не має параметрів) під час виділення області пам'яті для триелементного масиву. Як уже зазначалося вище, під час виділення області пам'яті для масиву автоматично викликається конструктор кожного елемента. Повідомлення Створення об'єкта 5, 6, 7 видано конструктором класу kooClass (який приймає три аргументи) під час виділення області пам'яті для одного об'єкта. Перші три повідомлення Руйнування об'єкта видані деструктором внаслідок видалення триелементного масиву, оскільки при цьому автоматично викликався деструктор кожного елемента масиву. Останнє повідомлення Руйнування об'єкта видане під час видалення одного об'єкта класу kooClass. Важливо розуміти, що, коли оператори new і delete перевизначені для конкретного класу, то внаслідок їх використання для даних інших типів будуть задіяні оригінальні версії операторів new і delete. Це означає, що при додаванні у функцію main() наступного рядка буде виконано стандартну версію оператора new:

int *f = new int; // Використовується стандартна версія оператора new.


 

А также другие работы, которые могут Вас заинтересовать

54108. Базовые функции культуры 35 KB
  Человекотворческая функция. или гуманистическая функция. цицерон говорил о ней - cultura animi - возделывание, взращивание духа. бердяев считал, что судьбу нашего отечества должны решать люди с обновленным духом, иной волей к преображению жизни. все остальные функции так или иначе связаны с этой и даже вытекают из нее.
54109. День матері, Година спілкування 34 KB
  З часом воно поширилось і в інші країни світу. В Україні це свято відзначають вже 83 роки. Особливо готуються до цього свята діти. Вони дарують матусям власноруч виготовленні сувеніри та багато теплих, ласкавих та ніжних слів. Дякують за тепло, турботу та безмежну любов своїх матусь).
54111. Матусю моя дорогенька, це свято даруєм тобі 55.5 KB
  Вчитель: 8 березня – свято наших мам, бабусь, сестричок. Разом із приходом весни завітало до нас це перше весняне свято. Його ми присвячуємо найдорожчим, найріднішим людям.
54112. Свято Матері 63.5 KB
  Її любов до дитини безмежна й щира. Матусю мила найрідніша в світі Ти наше сонце щире і ясне Ти дбаєш щоб завжди ми були ситі Твоя любов дитину не мине. Найбільше щастя мати для дитини Її любов і ласка щирий сміх.
54113. Вплив автотранспорту та сільгосптехніки на довкілля 260 KB
  Розвивати соціальні компетентно-комунікативні навички, приймати участь в дискусіях, співробітництві в групах, розвивати спостережливість, творчі, акторські здібності, розширювати кругозір студентів, викликати бажання до пошуку відповідей на запитання в книжках науково-пізнавального характеру, художній і народознавчій літературі, виховувати бережливе ставлення до природи.
54114. Мандрівка в місто культури 71.5 KB
  Раптом вибігає Поміха- Неуміха. Вона одягнена в чорне плаття, волосся розтріпане, на грудях плями, на обличчі - бруд. Вихоплює конверт, швидко продивляється лист і зловтішно викрикує:
54115. Зниклі цивілізації 52 KB
  Сьогодні ми зібралися у цій затишній кімнаті, щоб поговорити про відоме і невідоме, про знане і незнане, про фантастику і реальність. Свідомість людини швидко звикає до чогось нового, раніше незвіданого. Тунель під Ла-Маншем, пілотовані космічні польоти, всесвітня комп’ютерна мережа – усе це частина нашого сьогодення, реальності, яка ще років сто тому здалася б найсміливішою фантазією. Одначе для тих, хто народився після втілення в життя технічної новинки, воно вже не є чудом.
54116. ТЕМАТИЧНА МАНДРІВКА «МИ-УКРАЇНЦІ» 242.5 KB
  Мета: поглиблювати уявлення учнів про свою Батьківщину; розширювати поняття «громадянин», розвивати прагнення бути свідомим громадянином України, її патріотом; розвивати мовлення, уміння спостерігати; сприяти вихованню патріотичних почуттів.