当前位置:网站首页>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 ).
边栏推荐
- Render minecraft scenes into real scenes using NVIDIA GPU
- Sublime text configuring PHP compilation environment
- Redis——热点key问题
- 构建学习tensorflow
- Win10网络图标消失,网络图标变成灰色,打开网络设置闪退等问题解决
- 由於不正常斷電導致的unexpected inconsistency;RUN fsck MANUALLY問題已解决
- VSCODE 安装LATEX环境,参数配置,常见问题解决
- Usage of map and foreach in JS
- Latex在VSCODE中编译中文,使用中文路径问题解决
- kali最新更新指南
猜你喜欢
web自动中利用win32上传附件
Idea announced a new default UI, which is too refreshing (including the application link)
Redis——大Key問題
Redis - hot key issues
默认google浏览器打不开链接(点击超链接没有反应)
Latex error: the font size command \normalsize is not defined problem solved
ctf三计
Linux MySQL 5.6.51 community generic installation tutorial
Redis——Cluster数据分布算法&哈希槽
Code skills - Controller Parameter annotation @requestparam
随机推荐
自学table au
Utilisation de la carte et de foreach dans JS
(the 100th blog) written at the end of the second year of doctor's degree -20200818
部署api_automation_test过程中遇到的问题
qq邮箱接收不到jenkins构建后使用email extension 发送的邮件(timestamp 或 auth.......)
查询GPU时无进程运行,但是显存却被占用了
Unexpected inconsistency caused by abnormal power failure; Run fsck manually problem resolved
sprintf_ How to use s
AWD learning
web自动中利用win32上传附件
[daily question 1] write a function to judge whether a string is the string after the rotation of another string.
记录一次RDS故障排除--RDS容量徒增
蚂蚁集团g6初探
20201002 VS 2019 QT5.14 开发的程序打包
Linux MySQL 5.6.51 community generic installation tutorial
table 组件指定列合并行方法
Latex compilation error I found no \bibstyle &\bibdata &\citation command
Uploading attachments using Win32 in Web Automation
Latex 报错 LaTeX Error: The font size command \normalsize is not defined问题解决
sprintf_s的使用方法