当前位置:网站首页>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 ).
边栏推荐
- Vector types and variables built in CUDA
- sprintf_ How to use s
- automation - Jenkins pipline 执行 nodejs 命令时,提示 node: command not found
- Warp matrix functions in CUDA
- selenium+msedgedriver+edge浏览器安装驱动的坑
- Latex参考文献引用失败 报错 LaTeX Warning: Citation “*****” on page y undefined on input line *
- Redis - grande question clé
- ZZQ的博客目录--更新于20210601
- js中对于返回Promise对象的语句如何try catch
- Redis - big key problem
猜你喜欢
qq邮箱接收不到jenkins构建后使用email extension 发送的邮件(timestamp 或 auth.......)
js中正则表达式的使用
js中对于返回Promise对象的语句如何try catch
查询GPU时无进程运行,但是显存却被占用了
Win10桌面图标没有办法拖动(可以选中可以打开可以删除新建等操作但是不能拖动)
Pytest (1) case collection rules
Win10网络图标消失,网络图标变成灰色,打开网络设置闪退等问题解决
Blog directory of zzq -- updated on 20210601
web自动中利用win32上传附件
【文献阅读与想法笔记13】 Unprocessing Images for Learned Raw Denoising
随机推荐
Utilisation de la carte et de foreach dans JS
Codeforces Round #797 (Div. 3) A—E
Shardingsphere JDBC
js中map和forEach的用法
Présence d'une panne de courant anormale; Problème de gestion de la fsck d'exécution résolu
Warp shuffle in CUDA
Flask migrate cannot detect db String() equal length change
Flask-Migrate 检测不到db.string() 等长度变化
华为MindSpore开源实习机试题
Redis——大Key问题
20201025 Visual Studio2019 QT5.14 信号和槽功能的使用
Linux MySQL 5.6.51 Community Generic 安装教程
ModuleNotFoundError: No module named ‘jieba. analyse‘; ‘ jieba‘ is not a package
Detailed definition of tensorrt data format
Vscode installation, latex environment, parameter configuration, common problem solving
20201002 vs 2019 qt5.14 developed program packaging
Latex compiles Chinese in vscode and solves the problem of using Chinese path
automation - Jenkins pipline 执行 nodejs 命令时,提示 node: command not found
There are multiple good constructors and room will problem
奇葩pip install