PHPz2017-04-17 11:06:12
First of all, we need to distinguish between the two concepts new operator
and operator new
.
The former is the new 操作符
in the question.
Generally, when new an object, the bottom layer does the following two steps:
Allocate memory for the object;
Call the constructor to initialize this memory;
In the first step, memory is allocated using operator new
. @Feixia’s second example is a operator new
.
In the second step, call the constructor to initialize the memory. If inheritance is not involved, this step is very simple, just assign a value to the memory. Even if there is an inheritance relationship, the complexity lies in sorting out the inheritance relationship and virtual function table, which has little to do with this question.
The following focuses on operator new
in the first step. Its responsibility is to allocate memory.
operator new
is as given in @Feixia’s second example:
allocates memory and returns directly if successful, otherwise,
Check whether new_handler
is available, if available, call it and jump to 1, otherwise,
throws bad_alloc
exception.
The above new_handler
will try to free some memory.
After understanding this process, let’s extend the discussion to two other issues.
Does the null check in the following code snippet make sense?
Question * q = new Question;
if (q == NULL ) {
// 错误处理逻辑
}
We learned from the above that operator new
will call new_handler
when allocating memory fails to try to let the system release some memory, and then try to apply for memory again. If the memory in the system is really tight at this time, even if new_handler
is called, the system will not be able to get more memory, which will cause operator new
to fall into an infinite loop.
In short, operator new
either the memory is successfully applied for, or the endless loop fails.
Then, consider the second step of new operator
, calling the constructor to initialize the memory. As we all know, the C constructor does not return any return value. If you want the constructor to fail, you can only throw an exception.
From the above two points we can draw the conclusion: new Question
will never return a null pointer.
Furthermore, new Question
can fail in only two cases:
operator new
throws bad_alloc
exception;
The constructor throws its own exception.
So, does the null judgment logic in the above code snippet make sense? Is using try ... catch
to catch the exception of new
a better way to judge the failure of new
?
Customized memory management
Generally those who want to create new ones want to implement their own memory management (such as using a memory pool), and want to allow old code to enjoy the benefits of new memory management without changing the existing code. Welfare.
The specific method has been explained very clearly in the second article quoted by @Feixia. But because overloading new operator
may have a much greater impact on the entire system than initially imagined, the following two compromise solutions can be considered:
use placement new
;
Implement a new New (rather than overloading the original operator new
) and use it where really needed.
大家讲道理2017-04-17 11:06:12
new is a language feature of C , not a function.
It may call malloc, but how to allocate memory depends on the implementation. Compared with malloc, new will throw an exception by default when the application fails instead of returning 0 directly.
corresponds to new and delete, and they must appear in pairs. new[] and delete[] must appear at the same time.
迷茫2017-04-17 11:06:12
New is a C keyword. You can try to implement a new yourself. If necessary, use your own implemented functions to replace the default new to do some checks and other things.
For example, the writing method in the following link
cppreference link
void* operator new(std::size_t sz) {
return std::malloc(sz);
}
Implementation of complex points - in-depth exploration of C 's new/delete operator - Author @Kelvin
BLOG link, infringement and deletion
void * operator new(std::size_t size) throw(std::bad_alloc) {
if (size == 0)
size = 1;
void* p;
while ((p = ::malloc(size)) == 0) {
std::new_handler nh = std::get_new_handler();
if (nh)
nh();
else
throw std::bad_alloc();
}
return p;
}
void operator delete(void* ptr) {
if (ptr)
::free(ptr);
}
Added new_handler function to deal with insufficient memory