MyTetra Share
Делитесь знаниями!
Как в C++ пользоваться глобальным оператором new для выделения памяти
Время создания: 09.10.2024 12:58
Автор: Xintrea
Текстовые метки: c++, си++, глобальный, оператор, new, delete, placement, выделение, память, аллокация, аллокатор, синтаксис
Раздел: Компьютер - Программирование - Язык C++ (Си++)
Запись: xintrea/mytetra_syncro/master/base/172846789557c6kbovav/text.html на raw.github.com

В языке C++ есть обычный оператор new, а есть глобальная версия оператора new. И это разные вещи.


Обычный оператор new используется для создания объекта. По сути, он выделяет память под объект и затем сразу вызывает конструктор объекта.


Глобальная версия оператора new выделяет заданное в его параметре количество памяти (количество байт) без вызова конструктора для объекта (потому что она применяется не к объекту). После этого происходит просто возврат указателя на выделенную память.


Сигнатура глобального оператора new:



void* operator new(std::size_t size);



Глобальный оператор new выделяет блок памяти размером size байт. Поэтому он возвращает тип void*, который всегда можно преобразовать к указателю на любой заданный тип.


В случае неудачи оператор new (любой версии) выбрасывает исключение std::bad_alloc (такое поведение сделано начиная со стандарта C++98, а ранее new возвращал пустой указатель, см. далее).


Классический пример использования:



void* buffer = ::operator new(numBytes);



Когда используется глобальный оператор new:



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



Вот пример выделения памяти под объект без его инициализации:



// Выделение памяти без вызова конструктора

void* rawMemory = ::operator new(sizeof(MyClass));


// Приведение указателя на выделенную память к типу MyClass

MyClass* myObject = static_cast<MyClass*>(rawMemory);


// Вызов методов невозможен, пока не вызван конструктор


// Ручной вызов конструктора через placement new

new (myObject) MyClass;


// Теперь можно использовать объект, так как конструктор был вызван

myObject->sayHello();


// Явный вызов деструктора, так как память освобождается вручную

myObject->~MyClass();


// Освобождение памяти без вызова деструктора

::operator delete(rawMemory);



Здесь появляется еще один вид оператора new: "placement new". Placement new — это особая форма оператора new, которая позволяет разместить объект в заранее выделенной области памяти. В отличие от стандартного оператора new, который сначала выделяет память, а затем вызывает конструктор, placement new только вызывает конструктор объекта, используя уже выделенную память.


Синтаксис placement new:



new (pointer) Type(arguments);



где:


  • pointer — это указатель на заранее выделенную область памяти, в которой будет размещен объект.
  • Type — это тип объекта, который нужно создать.
  • arguments — это аргументы конструктора объекта (если таковые имеются).



Этот синтаксис не следует путать с nothrow-синтаксисом оператора new, который используется, чтобы вернуть поведение этого оператора таким, каким оно было до стандарта C++98:



int* ptr = new (std::nothrow) int[1000];


if (ptr == nullptr)

{

// Память не была выделена

}



Такой синтаксис блокирует генерацию исключения std::bad_alloc в случае, если память не была выделена а так же гарантирует что при возникновении ошибки выделения, указатель будет содержать нуливое значение.


Так же в этом разделе:
 
MyTetra Share v.0.65
Яндекс индекс цитирования