当前位置:网站首页>Operator new and placement new

Operator new and placement new

2022-06-11 19:20:00 Cai gaoshu

placement new Is to build a new object in the memory location specified by the user , This build process does not require additional memory allocation , Just call the constructor of the object . for instance :
class foo{};
foo* pfoo = new foo;
pfoo The address of the object pointed to cannot be determined ,new Did all this work . Step 1 allocate memory , The second step is to call the constructor of the class .

The operation of allocating memory is performed by operator new(size_t) To complete , If the class is overloaded operator new, Will call foo::operator new(size_t ), Otherwise, call Global ::operator new(size_t ), The latter is determined by C++ Provided by default .

operator new  

operator new Is the function , There are three forms ( front 2 A constructor that does not call , This is different from new operator):  
void* operator new (std::size_t size) throw (std::bad_alloc);  
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();  
void* operator new (std::size_t size, void* ptr) throw();  
The first distribution size Bytes of storage space , And align the object types in memory . If it works , Returns a non null pointer to the first address . Failure throw bad_alloc abnormal .  
The second method does not throw an exception when the allocation fails , It returns a NULL The pointer .  
The third is placement new edition , It is essentially right operator new overloaded , Defined in #include <new> in . It does not allocate memory , Call the appropriate constructor in ptr Construct an object where it refers to , Then return the argument pointer ptr.  
First of all 、 The second version can be overloaded by users , Define your own version , The third kind of placement new Do not overload .  
A* a = new A; // Call the first   
A* a = new(std::nothrow) A; // Call the second   
new (p)A(); // Call the third   
new (p)A() call placement new after , Also in the p On the call A::A(), there p It can be dynamically allocated memory in the heap , It can also be a buffer in the stack .   

heavy load operator new:

#include <iostream>
#include <string>
using namespace std;

class X
{
public:
	X()
	{
		cout << "X's constructor" << endl;
	}
	~X()
	{
		cout << "X's destructor" << endl;
	}
	void* operator new(size_t size, string str)
	{
		cout << "operator new size " << size << " with string " << str << endl;
		return ::operator new(size);// What is overloaded here is the number operator new ?  Called X()
	}
	void operator delete(void* pointer)
	{
		cout << "operator delete" << endl;
		::operator delete(pointer);
	}
private:
	int num;
};

int main()
{
	X* p = new("A new class") X;
	delete p;
	return 0;
}

  Output results :

placement new

placement new How does it work , The original new The two steps of work are separated . The first step is to allocate your own memory , Step 2: you call the constructor of the class to build a new object in your allocated memory .

placement new The advantages of :
1) Build objects on allocated memory , It's fast to build . It is suitable for people who have high requirements for time , Long running applications that don't want to be interrupted .
2) The allocated memory can be reused , Effectively avoid memory fragmentation .

placement new And other ordinary new The difference is , It has another parameter in parentheses . such as :

Widget * p = new Widget; //ordinary new  // ordinary new pi = new (ptr) int;
pi = new (ptr) int; //placement new

The parameter in parentheses is a pointer , It points to a memory buffer ,placement new An object will be allocated on this buffer .Placement new The return value of is the address of the constructed object ( For example, the transfer parameter in the deduction number ).placement new Mainly applicable to : In very time critical applications , Because the time allocated by these programs is certain ; A program that runs for a long time without interruption ; And execute a garbage collector (garbage collector).

Usage method

In many cases ,placement new And other common new Somewhat different . Here are the steps to use it .

First step   Cache pre allocation

To ensure the passage of placement new Of the cache used memory alignmen( Memory queue ) Correct preparation , Use ordinary new To allocate it :

class Task ;

char * buff = new [sizeof(Task)]; // Allocate memory

(auto perhaps static Memory is not always arranged correctly for each object type , So we can't use placement new Use them .)

The second step : The allocation of objects

Call... In the cache that has just been allocated placement new To construct an object .

Task *ptask = new(buff) Task

The third step : Use

Use the allocated objects in the normal way :

ptask->suspend();

ptask->resume();

//...

Step four : The analysis of objects

After using this object, you must call its destructor to destroy it . Call the destructor as follows :

ptask->~Task(); // Call the external destructor

Step five : Memory free

You can reuse the cache and assign it a new object ( Repeat step 2,3,4) If you don't plan to use this cache again , It can be released like this :

delete [] buff;

Skipping any step may cause the runtime to crash , Memory leak , And other unexpected situations .

原网站

版权声明
本文为[Cai gaoshu]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203011832218339.html