C++ operator overloading new delete

 In C++, operator overloading gives C++ great flexibility. In addition to overloading operators such as addition, subtraction, multiplication and division, new and delete can also be overloaded by users.

Why overload new and delete?

 Overloading new and delete mainly has the following two purposes:
1. Do not allocate memory to the heap (new usually allocates memory to the heap), or reduce fragmented memory.
2. Some records can be made, such as tracking the actual usage of memory to check whether there is a memory leak.

How to overload new and delete?

new operator overloading

 C++ provides us with 4 new operator overloads:

    void* operator new  (std::size_t count );  
    void* operator new[](std::size_t count );  
    void* operator new  (std::size_t count, const std::nothrow_t& tag);  
    void* operator new[](std::size_t count, const std::nothrow_t& tag);  

 It's not hard to see that each function has something in common:

  1. Both take a parameter of type size_t , which specifies the size of the allocated memory.
  2. The return value must be of type void* , which is used to return the first address of the allocated memory.

 If the memory cannot be allocated correctly, then 1 2 will trigger a std::bad_alloc exception, and 3 4 will return a null pointer NULL.

  • Under normal circumstances, 1 2 is sufficient for use
  • 2 4 dedicated to handling memory allocations for arrays

But it should be noted that the overload of new only changes the way of memory allocation, and cannot change the structure of the object. Similarly, the following delete only changes the way of memory release.

delete operator overloading

And the delete operator overloads in 5:

	void operator delete  (void* ptr); 	
	void operator delete[](void* ptr);
	void operator delete  (void* ptr, const std::nothrow_t& tag);
	void operator delete[](void* ptr, const std::nothrow_t& tag);
	void operator delete  (void* ptr, std::size_t sz);
	void operator delete[](void* ptr, std::size_t sz);

delete will accept a parameter of type void*, which is the first address of the memory to be released.

Code

 In the reasons for overloading above, we mentioned that overloading new and delete can help us observe our memory usage, and we will implement this function in the future.


	// myNew.hpp
	
	#ifndef MY_NEW
	#define MY_NEW
	
	#include <cstdlib>
	#include <iostream>
	#include <new>
	
	static std::size_t alloc{
    
    0};
	static std::size_t dealloc{
    
    0};
	
	void* operator new(std::size_t sz)
	{
    
    
	    alloc+= 1;//将可以观测内存分配的情况
	    return std::malloc(sz);
	}
	
	void operator delete(void* ptr) noexcept
	{
    
    
	    dealloc+= 1;//将可以观测内存释放的情况
	    std::free(ptr);
	}
	//打印内存的实际使用情况
	void getInfo()
	{
    
    
	    
	    std::cout << std::endl;
	 
	    std::cout << "Number of allocations: " << alloc << std::endl;
	    std::cout << "Number of deallocations: " << dealloc << std::endl;
	    
	    std::cout << std::endl;
	}
	
	#endif // MY_NEW

 Of course, we can also choose to put the allocated memory into an array, and detect whether the memory leaks by traversing the array


	// myNew3.hpp
	
	#ifndef MY_NEW3
	#define MY_NEW3
	
	#include <algorithm>
	#include <cstdlib>
	#include <iostream>
	#include <new>
	#include <string>
	#include <array>
	
	int const MY_SIZE= 10;
	
	std::array<void* ,MY_SIZE> myAlloc{
    
    nullptr,};//存储内存地址以及大小的数组
	    
	void* operator new(std::size_t sz)
	{
    
    
	    static int counter{
    
    };
	    void* ptr= std::malloc(sz);
	    myAlloc.at(counter++)= ptr;//向数组中添加元素
	    std::cerr << "Addr.: " << ptr << " size: " << sz << std::endl;
	    return ptr;
	}
	
	void operator delete(void* ptr) noexcept
	{
    
    
	    auto ind= std::distance(myAlloc.begin(),std::find(myAlloc.begin(),myAlloc.end(),ptr));//找到目标内存的下标
	    myAlloc[ind]= nullptr;
	    std::free(ptr);
	}
	
	void getInfo()
	{
    
    
	    
	    std::cout << std::endl;
	     
	    std::cout << "Not deallocated: " << std::endl;
	    for (auto i: myAlloc)
		{
    
    
	        if (i != nullptr ) std::cout << " " << i << std::endl;//打印没有被释放的内存
	    }
	    
	    std::cout << std::endl;
	    
	}
	
	#endif // MY_NEW3

Guess you like

Origin blog.csdn.net/qq_43550173/article/details/113524470