Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

3.6. Перегрузка операции new

Лекция



Привет, сегодня поговорим про перегрузка операции new, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое перегрузка операции new , настоятельно рекомендую прочитать все из категории С++ (C plus plus).

3.6.1.Синтаксис

     Операция new, заданная по умолчанию, может быть в двух формах:

1)  new тип <инициализирующее выражение>

2)  new тип[];

Первая форма используется не для массивов, вторая- для массивов.

Перегруженную операцию new можно определить в следующих формах, соответственно для не массивов и для массивов:

void* operator new(size_t  t[,остальные аргументы] );

void* operator new[](size_t  t[,остальные аргументы] );

Первый и единственный обязательный аргумент t всегда должен иметь тип size_t. Если аргумент имеет тип size_t, то в операцию-функцию new автоматически подставляется аргумент sizeof(t), т.е. она получает значение, равное размеру объекта t в байтах.

Например, пусть задана следующая функция:

void* operator new(size_t  t,int n){return new char[t*n];}

и она вызывается следующим  образом:

double *d=new(5)double;

Здесь t=double, n=5.

     В результате после вызова значение t в теле функции будет равно sizeof(double).

При перегрузке операции new появляется несколько глобальных операций new, одна из которых определена в самом языке по умолчанию, а другие являются перегруженными. Возникает вопрос: как различить такие операции? Это делается путем изменения числа и типов их аргументов. При изменении только типов аргументов может возникнуть неоднозначность, являющаяся  следствием возможных преобразований этих типов друг к другу. При возникновении такой неоднозначности следует при обращении к new задать тип явно, например:

new((double)5)double;

     Одна из причин, по которой перегружается операция new, состоит в стремлении придать ей дополнительную семантику, например, обеспечение диагностической информацией или устойчивости к сбоям. Кроме того класс может обеспечить более эффективную схему распределения памяти чем та, которую предоставляет система.

В соответствии со стандартом С++ в заголовочном файле <new> определены следующие функции-операции new, позволяющие передавать, наряду с обязательным первым size_t аргументом и другие. 

void* operatop new(size_t t)throw(bad_alloc);

void* operatop new(size_t t,void* p)throw();

void* operatop new(size_t t,const nothrow&)throw();

void* operatop new(size_t t,allocator& a);

void* operatop new[](size_t t)throw(bad_alloc);

void* operatop new[](size_t t,void* p)throw();

void* operatop new[](size_t t,const nothrow&)throw();

     Эти функции используют генерацию исключений(throw) и собственный распределитель памяти(allocator).

     Версия с nothrow выделяет память как обычно, но если выделение заканчивается неудачей, возвращается 0, а не генерируется bad_alloc. Об этом говорит сайт https://intellect.icu . Это позволяет нам для выделения памяти использовать стратегию обработки ошибок до генерации исключения.

 

3.6.2.Правила использования операции new

1.   Объекты, организованные с помощью new имеют неограниченное время жизни. Поэтому область памяти должна освобождаться  оператором delete.

2.   Если резервируется память для массива, то операция new возвращает указатель на первый элемент массива.

3.   При резервировании памяти для массива все размерности должны быть выражены положительными величинами.

4.   Массивы нельзя инициализировать.

5.   Объекты классов могут организовываться с помощью операции new, если класс имеет конструктор по умолчанию.

6.   Ссылки не могут организовываться с помощью операции new, так как для них не выделяется память.

Операция new самостоятельно вычисляет потребность в памяти для организуемого типа данных, поэтому первый параметр операции всегда имеет тип size_t.

3.6.3.Обработка ошибок операции new

     Обработка ошибок операции new происходит в два этапа:

1.   Устанавливается, какие предусмотрены функции для обработки ошибок. Собственные функции должны иметь тип new_handler и создаются с помощью функции set_new_handler. В файле new.h объявлены

typedef void(*new_handler)();

new_handler set_new_handler(new_handler new_p);

2.   Вызывается соответствующая new_handler функция. Эта функция должна:

-либо вызвать bad_alloc исключение;

-либо закончить программу;

-либо освободить память и попытаться распределить ее заново.

Диагностический класс bad_alloc объявлен в new.h.

     В реализации ВС++ включена специальная глобальная переменная _new_handler, значением которой является указатель на new_handler функцию, которая выполняется при неудачном завершении new. По умолчанию, если операция new не может выделить требуемое количество памяти, формируется  исключение bad_alloc. Изначально это исключение называлось xalloc и определялось в файле except.h. Исключение xalloc продолжает использоваться во многих компиляторах. Тем не менее, оно вытесняется определенным в стандарте С++ именем bad_alloc.

Рассмотрим несколько примеров.

Пример 3.6.1

 

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

#include <iostream>

#include <new>

void main()

{double *p;

try{

p=new double[1000];

cout<<"Память выделилась успешно"<<endl;

}

catch(bad_alloc xa)

{cout<<"Ошибка выделения памяти\n";

cout<<xa.what();  return;} }

 

Пример 3.6.2

 

     Поскольку в предыдущем примере при работе в нормальных условиях ошибка выделения памяти маловероятна, в этом примере ошибка выделения памяти достигается принудительно. Процесс выделения памяти длится до тех пор, пока не произойдет ошибка.

#include <iostream>

#include <new>

void main()

{double *p;

do{

try{

p=new double[1000];

//cout<<"Память выделилась успешно"<<endl;

}

catch(bad_alloc xa)

{cout<<"Ошибка выделения памяти\n";

cout<<xa.what();

 return;}

}while(p);

}

 

 

Пример 3.6.3

 

Демонстрируется перегруженная форма операции new-операция new(nothow).

#include <iostream>

#include <new>

void main()

{double *p;

struct nothrow noth_ob;

do{

p=new(noth_ob) double[1000];

if(!p) cout <<"Ошибка выделения памяти\n";

else cout<<"Память выделилась успешно\n";

}while(p);

}

 

Пример 3.6.4

      Демонстрируются различные формы перегрузки операции new.

#include<iostream.h>

#include<new.h>

double *p,*q,**pp;

class demo

{ int value;

public:

  demo(){value=0;}

  demo(int i){value = 1;}

  void* operator new(size_t t,int,int);

  void* operator new(size_t t,int);

  void* operator new(size_t t,char*);

  };

 

void* demo :: operator new(size_t t,int i, int j)

{

 if(j)  return new(i)demo;

 else return NULL;

}

void* demo :: operator new(size_t t,int i)

{demo* p= ::new demo;

  (*p).value=i;

  return p;

}

void* demo::operator new(size_t t,char* z)

{

return ::new(z)demo;

}

 

void main()

{ class demo *p_ob1,*p_ob2;

//  struct nothrow noth_ob;

  p=new double;

  pp=new double*;

  p=new double(1.2);  //инициализация

  q=new double[3];    //массив

  p_ob1=new demo[10]; //массив объектов demo

  void(**f_ptr)(int); //указатель на указатель на функцию

  f_ptr=new(void(*[3])(int)); //массив указателей на функцию

  char z[sizeof(demo)]; //резервируется память в соответствии с величиной              //demo

  p_ob2=new(z)demo;   //организуется demo-объект в области памяти на //которую указывает переменная z

  p_ob2=new(3)demo;   //demo-объект с инициализацией

  p_ob1=new(3,0)demo; //возвращает указатель NULL

 // p_ob2=new(noth_ob)demo[5];//массив demo-объектов,

  // в случае ошибки возвращает NULL

  }

В общем, мой друг ты одолел чтение этой статьи об перегрузка операции new. Работы впереди у тебя будет много. Смело пиши комментарии, развивайся и счастье окажется в твоих руках. Надеюсь, что теперь ты понял что такое перегрузка операции new и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории С++ (C plus plus)

Из статьи мы узнали кратко, но содержательно про перегрузка операции new
создано: 2015-12-20
обновлено: 2021-03-13
162



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей

Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

С++ (C plus plus)

Термины: С++ (C plus plus)