当前位置:网站首页>Overload global and member new/delete
Overload global and member new/delete
2022-07-02 06:43:00 【From then on, keep a low profile】
1. Override Global new/delete
heavy load ::operator new、::operator delete、::operator new[]、operator delete[]
Be careful : If the overloaded is global , So when you create an object, the compiler calls operator new、operator delete Will call their overloaded version ; If overloaded class members operator new, Then only when creating and releasing this kind of object, the compiler calls its own overloaded operator new、operator delete edition .
If Fraction Class does not override the original new/delete, Then it will directly call the global new/delete:
class Fraction
{
public:
Fraction(int num, int den = 1) :m_numerator(num), m_denominator(den) {}
private:
int m_numerator;// molecular
int m_denominator;// The denominator
};
void* myAlloc(size_t size)
{
return malloc(size);
}
inline void* operator new(size_t size)
{
cout << " Overloaded global new\n" << endl;
return myAlloc(size);
}
void operator delete(void* ptr /*,size_t*/)// The second parameter has a default value , It doesn't matter if you don't write
{
cout << " Overloaded global delete\n" << endl;
free(ptr);
}
int main()
{
Fraction* f = new Fraction(1);// Overloaded global new
delete f;// Overloaded global delete
}
2. Override member new/delete
rewrite new and new[] The difference is new The constructor will only be called once , and new[] Will call multiple times ( The number is [] Inner number ).
class Foo
{
public:
int m_id;
long m_data;
string m_str;
public:
Foo() :m_id(0) { cout << " Parameterless constructor call " << endl; }
Foo(int i) :m_id(i) { cout << " Call the parameter constructor " << endl; }
~Foo() { cout << " Destructor call " << endl; }
static void* operator new(size_t size)
{
cout << "operator new call ,size = " << size << endl;
Foo* p = (Foo*)malloc(size);
return p;
}
static void operator delete(void* ptr, size_t size)
{
cout << "operator delete call ,size = " << size << endl;
free(ptr);
}
static void* operator new[](size_t size)
{
cout << "operator new[] call ,size = " << size << endl;
Foo* p = (Foo*)malloc(size);
return p;
}
static void operator delete[](void* ptr, size_t size)
{
cout << "operator delete[] call ,size = " << size << endl;
free(ptr);
}
};
int main()
{
cout << sizeof(Foo) << endl;//48
Foo* pf = new Foo;// Call your own rewritten operator new
delete pf;// Call your own rewritten operator delete
Foo* gnew_pf = ::new Foo;// Will bypass their own rewriting operator new, Force global new
::delete gnew_pf;// Will bypass their own rewriting operator delete, Force global delete
Foo* pfAry = new Foo[3];
delete[] pfAry;
}
Compile output :
48
operator new call ,size = 48
Parameterless constructor call
Destructor call
operator delete call ,size = 48
Parameterless constructor call
Destructor call
operator new[] call ,size = 152
Parameterless constructor call
Parameterless constructor call
Parameterless constructor call
Destructor call
Destructor call
Destructor call
operator delete[] call ,size = 152
As can be seen from the results ,Foo Class size is 48 byte , call operator new after , open up size by 48 byte ; call operator new[3] after , open up size by 152 byte ,operator new[] and operator delete[] Are called only once , Constructors and destructors call 3 Time .
call operator new[3] Should have opened up size by 48*3=144 Byte space , But why did it open up 152 Bytes ?
This is because when opening up array space , stay 64 There needs to be a 8 The space of byte size is used to store the number of array members .32 This size is 4 byte .
3. placement new
We can overload class members operator new(), Write multiple versions , The premise is that each version of the declaration must have a unique parameter column , The first parameter must be size_t, Other parameters are represented by new As specified by the placement arguments For the initial value . Appear in the new(…) In parentheses is the so-called placement arguments.
Foo *pf = new(300,'c') Foo;// new() The actual parameters of are three
for example :
//1. This is general operator new() overloaded
static void* operator new(size_t size)
{
cout << "operator new call ,size = " << size << endl;
Foo* p = (Foo*)malloc(size);
return p;
}
//2. This is what the standard library has provided placement new() Overloaded form of
void* operator new(size_t size, void* start)
{
return start;
}
//3. This is brand new placement new
void* operator new(size_t size, long extra)
{
cout << "extra Called " << endl;
return malloc(size + extra);
}
//4. This is another placement new
void* operator new(size_t size, long extra, char init)
{
return malloc(size + extra);
}
Foo* extrapf = new(200) Foo;// What is called is 3 individual placement new.
We can also overload class members operator delete(), Write multiple versions . But they will never be delete call . Only when new The called constructor throws an exception exception, Will call the corresponding operator new() Overloaded version of operator delete(). It can only be called like this , Mainly used to return failed Completely created Memory used by objects of .
#include <iostream>
using namespace std;
// Your own exception class
class Bad : public exception
{
public:
Bad(const char* err) {
this->m_pErr = new char[strlen(err) + 1];
strcpy_s(this->m_pErr, strlen(err) + 1, err);
}
~Bad() {
if (this->m_pErr != NULL) {
delete[] this->m_pErr;
this->m_pErr = NULL;
}
}
virtual const char* what() const
{
return m_pErr;
}
public:
char* m_pErr;
};
class Foo
{
public:
int m_id;
long m_data;
string m_str;
public:
Foo() :m_id(0) { cout << " Parameterless constructor call " << endl; }
Foo(int i) :m_id(i)
{
cout << " Call the parameter constructor " << endl;
// An exception is deliberately thrown here , The back corresponds to placement delete It's called
throw Bad(" The constructor threw an exception ");// If you don't throw an exception , Only general operator delete.
}
~Foo() { cout << " Destructor call " << endl; }
//1. This is general operator new() overloaded
static void* operator new(size_t size)
{
cout << "operator new call ,size = " << size << endl;
Foo* p = (Foo*)malloc(size);
return p;
}
//2. This is what the standard library has provided placement new() Overloaded form of
void* operator new(size_t size, void* start)
{
return start;
}
//3. This is brand new placement new
void* operator new(size_t size, long extra)
{
cout << "extra new Called " << endl;
return malloc(size + extra);
}
//4. This is another placement new
void* operator new(size_t size, long extra, char init)
{
return malloc(size + extra);
}
//1. This is a general operator delete() heavy load
static void operator delete(void* ptr, size_t size)
{
cout << "operator delete call ,size = " << size << endl;
free(ptr);
}
//2. This is the correspondence 2new Of delete
void operator delete(void*, void*)
{
cout << "delete(void*, void*)" << endl;
}
//3. This is the correspondence 3new Of delete
void operator delete(void* ptr, long size)
{
// Here size=200
cout << "extra delete Called ,size = " << size << endl;
free(ptr);
}
//4. This is the correspondence 4new Of delete
void operator delete(void*, long, char)
{
cout << "operator delete(void*, long, char)" << endl;
}
};
int main()
{
// Corresponding placement delete Is called the
try
{
Foo* extrapf = new(200) Foo(1);
delete extrapf;
}
catch (Bad& e) {
cout << e.what() << endl;
}
}
Compile output :
extra new Called
Call the parameter constructor
extra delete Called ,size = 200
The constructor threw an exception
Use placement new To open up memory space , When the constructor emits an exception , Even if the corresponding placement delete function , The compiler will not report any errors . The default meaning is : We gave up dealing with exceptions thrown by constructors . Exceptions will be passed up by default (operator delete It will not be called ).
边栏推荐
- After reading useful blogs
- Detailed definition of tensorrt data format
- Redis——大Key问题
- web自动化切换窗口时报错“list“ object is not callable
- Win10桌面图标没有办法拖动(可以选中可以打开可以删除新建等操作但是不能拖动)
- Fe - weex uses a simple encapsulated data loading plug-in as the global loading method
- Function execution space specifier in CUDA
- Name six schemes to realize delayed messages at one go
- CUDA user object
- selenium+msedgedriver+edge浏览器安装驱动的坑
猜你喜欢

Find the highest value of the current element Z-index of the page

Code skills - Controller Parameter annotation @requestparam

ZZQ的博客目录--更新于20210601

FE - 微信小程序 - 蓝牙 BLE 开发调研与使用

js中对于返回Promise对象的语句如何try catch

Linux MySQL 5.6.51 community generic installation tutorial
![[literature reading and thought notes 13] unprocessing images for learned raw denoising](/img/a5/ed26a90b3edd75a37b2e5164f6b7d2.png)
[literature reading and thought notes 13] unprocessing images for learned raw denoising

The win10 network icon disappears, and the network icon turns gray. Open the network and set the flash back to solve the problem

Log (common log framework)

apt命令报证书错误 Certificate verification failed: The certificate is NOT trusted
随机推荐
Pytest (3) parameterize
Kali latest update Guide
奇葩pip install
Render minecraft scenes into real scenes using NVIDIA GPU
Storage space modifier in CUDA
Record RDS troubleshooting once -- RDS capacity increases dramatically
Flask migrate cannot detect db String() equal length change
Flask-Migrate 检测不到db.string() 等长度变化
Redis——热点key问题
Utilisation de la carte et de foreach dans JS
Redis - grande question clé
selenium+msedgedriver+edge浏览器安装驱动的坑
Latex在VSCODE中编译中文,使用中文路径问题解决
Detailed definition of tensorrt data format
FE - weex 开发 之 使用 weex-ui 组件与配置使用
Présence d'une panne de courant anormale; Problème de gestion de la fsck d'exécution résolu
Distributed transactions: the final consistency scheme of reliable messages
Fe - eggjs combined with typeorm cannot connect to the database
Linux MySQL 5.6.51 community generic installation tutorial
2020-9-23 QT的定时器Qtimer类的使用。