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.


 

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

47908. Інтелектуальна власність 465 KB
  Ці та інші результати розумової праці мають назву об'єкти права інтелектуальної власності або інтелектуальна власність . Після проголошення незалежності України суттєво змінилося відношення до інтелектуальної власності. Якщо за радянських часів виключне право розпоряджатися інтелектуальною власністю належало державі то відтепер воно належить насамперед творцю цієї власності. Одним із феноменальних явищ кінця XX століття є масова поява на ринку нового виду товару інтелектуальної власності.
47909. ПОЛЬЩА У 70 – 80-Х РОКАХ ХХ СТ 164 KB
  Для покриття боргів уряд удався до короткотермінових кредитів що лише відсунуло загрозу банкрутства але не ліквідувало його. Намагаючись послабити тиск на споживчий ринок уряд удався до випробуваної політики затягування поясів . під тиском громадськості уряд прийняв рішення про умовне звільнення учасників червневих подій. А почалося все з рішення уряду ввести комерційні ціни на м'ясо щоб у такий спосіб роздобути кошти для виплати боргів західним країнам.
47910. Соціологія рекламної та ПР-діяльності 458 KB
  СФЕРА ВИРОБНИЦТВА ЯК ФАКТОР ПОЯВИ РЕКЛАМИ План. Розглянемо соціологічні умови появи реклами. Реклама як масове явище не могла виникнути раніше ніж виникли ринок виробника товарів ринок інформаційних засобів розміщення реклами та ринок споживачів рекламованих товарів і послуг – три основних фактори появи реклами як масового явища. Тому зараз коли історія ринку як елемента соціального розвитку налічує вже тисячоліття така рекламна ситуація називається рекламою на місці продажу та визначається лише як специфічна частина масових рекламних...
47911. Біохімічне обгрунтування методики занять фізичною культурою і спортом з особами різного віку та статі 369 KB
  Перше дитинство 47 років 5. Друге дитинство 812 років хлопчики 811 років дівчинки. Підлітковий пубертатний 1316 років хлопчики вік 1215 років дівчатка. Зрілий вік: I період 2235 років чоловіки 2135 років жінки.
47912. ПОНЯТТЯ ТА ПОТЕНЦІЙНІ ЗАГРОЗИ БЕЗПЕЦІ ПІДПРИЄМНИЦЬКОЇ ДІЯЛЬНОСТІ 1.41 MB
  Провідні українські експерти визнають той факт що багаторівнева економіка потребує також різноманітних видів забезпечення економічної фізичної та інших видів безпеки та організації охорони. Це дає можливість вибору для клієнтів аналізу та порівняння різних форм охоронної діяльності і в кінцевому результаті сприяє в цілому підвищенню рівня безпеки підприємницької діяльності в Україні. В умовах збільшення частки приватного капіталу в економіці України розвитку малого та середнього бізнесу а також роздержавлення стратегічних об'єктів...
47913. Призначення випробувань, впливаючі фактори при експлуатації РЕМА і ЕОЗ 1.59 MB
  Призначення випробувань впливаючі фактори при експлуатації РЕМА і ЕОЗ. Слід виділити три групи завдань вирішуваних проведенням випробувань: здобуття емпіричних даних необхідних для проектування апаратури; встановлення відповідності виробу проектним вимогам; визначення граничного стану ЕА. Цілі випробувань не постійні: вони міняються на різних етапах проектування і виготовлення апаратури. Перерахуємо основні цілі випробувань ЕА : Експериментальне підтвердження теоретичних розрахунків прийнятих допущень і гіпотез заданих показників якості...
47914. Сучасний стан охорони праці в Україні. Мета та завдання дисципліни Основи охорони праці 19.12 MB
  Виявити мету та завдання дисципліни Основи охорони праціâ€œ. Визначити правові та організаційні питання охорони праці. Сучасний стан охорони праці в Україні.
47916. Звітність підприємства. Методичні вказівки 334 KB
  Звіт про рух грошових коштів Тема 5 Звіт про власний капітал Тема 6. Фінансова бухгалтерська звітність документи які містять інформацію про фінансовий стан результати діяльності про рух грошових коштів підприємства за звітний період і тому подібне. № 2 Звіт про рух грошових коштів ф. № 4 представляється за станом на 31 грудня Звіт про рух грошових коштів ф.