当前位置:网站首页>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 ).
边栏推荐
- 查询GPU时无进程运行,但是显存却被占用了
- Redis——热点key问题
- Warp matrix functions in CUDA
- 2020-9-23 use of QT timer qtimer class.
- Flask-Migrate 检测不到db.string() 等长度变化
- Fe - wechat applet - Bluetooth ble development research and use
- Vector types and variables built in CUDA
- Vscode installation, latex environment, parameter configuration, common problem solving
- Detailed definition of tensorrt data format
- Unexpected inconsistency caused by abnormal power failure; Run fsck manually problem resolved
猜你喜欢

No process runs when querying GPU, but the video memory is occupied

如何调试微信内置浏览器应用(企业号、公众号、订阅号)

Pytest (1) case collection rules

Solution to the black screen of win computer screenshot

Redis——热点key问题

Build learning tensorflow

apt命令报证书错误 Certificate verification failed: The certificate is NOT trusted

Log (common log framework)

Pytest (2) mark function

AWD学习
随机推荐
Promise中有resolve和无resolve的代码执行顺序
Sublime text configuring PHP compilation environment
[daily question 1] write a function to judge whether a string is the string after the rotation of another string.
Tensorrt command line program
Distributed transactions: the final consistency scheme of reliable messages
kali最新更新指南
Storage space modifier in CUDA
(第一百篇BLOG)写于博士二年级结束-20200818
Kotlin - verify whether the time format is yyyy MM DD hh:mm:ss
Sentry搭建和使用
Latex error: the font size command \normalsize is not defined problem solved
How to try catch statements that return promise objects in JS
js中对于返回Promise对象的语句如何try catch
FE - weex 开发 之 使用 weex-ui 组件与配置使用
web自动化切换窗口时报错“list“ object is not callable
[literature reading and thought notes 13] unprocessing images for learned raw denoising
CTF three count
默认google浏览器打不开链接(点击超链接没有反应)
底层机制Mvcc
Vscode installation, latex environment, parameter configuration, common problem solving