Note: The following tests are performed under VS2015, and other compilers may be slightly different.
Continue to clean up the rest of the content of the next chapter, the article involved a lot of the content of this article, and then a specific look.
second, operator New/delete, and its corresponding array version operator new[]/delete[].
1. Operator new, there are three common forms:
A. throw:void* operator new (std::size_t size) throw (std::bad_alloc), corresponding to the void operator delete (void* p)
B. No throw:void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw (), corresponding to the void operator Del Ete (void* p, const std::nothrow_t& nothrow_value);
C. placement:void* operator new (std::size_t size, void* ptr) throw ();
A, B is only the difference between throwing an exception, when the allocation fails, the former throws a Bad_alloc exception, which does not throw an exception, and returns NULL. They all allocate a contiguous memory of size.
The role of C is to construct objects directly on existing memory. The equivalent of the new operator omitted the first step to allocate memory, which is a global overloaded version of operator new in C + +, which accepts two parameters, a memory block size a pointer to the block memory, The implementation code is simple and returns the pointer directly, but this is only the first step, and the second operation is to invoke the constructor of the related class, construct the class object on the memory block, and then point to the newly constructed class object.
Operator New/delete overloads are classified as overloads and global overloads in the class.
Write a few demo code below to actually look:
First look at the overloads in this class:
I. For a,b two types:
Coperatortest declaration and its definition:
Class Coperatortest
{public
:
coperatortest ();
Virtual ~coperatortest ();
void* operator new (size_t size);
void* operator new (size_t size, const std::nothrow_t& nothrow_value);
void operator Delete (void* p);
void Coperatortest::operator Delete (void* p, const std::nothrow_t& nothrow_value);
Coperatortest::coperatortest (void)
{
std::cout << "coperatortest ()" << Std::endl;
}
Coperatortest::~coperatortest (void)
{
std::cout << "~coperatortest ()" << Std::endl;
}
void* coperatortest::operator New (size_t size)
{
std::cout << "Coperatortest::operator New with Size:" << size << Std::endl;
return malloc (size);
}
void Coperatortest::operator Delete (void* p)
{
std::cout << "coperatortest::operator Delete" << Std::endl;
Free (p);
}
void* coperatortest::operator New (size_t size, const std::nothrow_t& nothrow_value)
{
Std::cout < < "Coperatortest::nothrow operator new with size:" << size << Std::endl;
return malloc (size);
}
void Coperatortest::operator Delete (void* p, const std::nothrow_t& nothrow_value)
{
std::cout << Coperatortest::nothrow operator Delete "<< Std::endl;
Free (p);
}
The call is as follows:
Coperatortest::operator new
coperatortest* pop1_0 = static_cast<coperatortest*> (COperatorTest::o Perator New (sizeof (coperatortest)));
Coperatortest::operator Delete
coperatortest::operator Delete (POP1_0);
Std::cout << Std::endl;
Coperatortest::nothrow operator new
coperatortest* pop2_0 = static_cast<coperatortest*> (COperatorTest: : operator new (sizeof (coperatortest), Std::nothrow));
Coperatortest::nothrow operator delete
coperatortest::operator Delete (pop2_0, std::nothrow);
The results of the operation are as follows
class Name:: operator New/deleteTo invoke the corresponding operator of this class Overload:
Ii. for placement New/delete, refer to the following example:
Class Coperatortest
{public
:
coperatortest ();
Virtual ~coperatortest ();
void* operator new (size_t size, void* p);
void operator Delete (void* p);
void* coperatortest::operator New (size_t size, void* p)
{
std::cout << "coperatortest::p lacement operator new with size: "<< size << Std::endl;
Just return p without no change return
p;
}
void Coperatortest::operator Delete (void* p)
{
std::cout << "coperatortest::operator Delete" << Std::endl;
Free (p);
}
The call is as follows:
Coperatortest:: Placement new, placement new is a overload version of global operator new.
So we cannot define another global overloaded one
coperatortest* pop3_0 = static_cast<coperatortest*> (malloc (sizeof (coperatortest));
coperatortest* pop3_1 = new (POP3_0) coperatortest ();
Pop3_1->~coperatortest ();
Coperatortest::operator Delete (pop3_1);
Std::cout << Std::endl;
Output, note that the above is called by the new operator, called directly: (coperatortest*) operator new (sizeof (coperatortest), pop3_0), but it doesn't make sense. :D
Then look at the global version of the overload, this time three look together, function definition and call:
void* operator new (size_t size) {std::cout << "global operator New with size:" << size << Std::endl
;
return malloc (size);
} void operator Delete (void* p) {std::cout << "global operator delete" << Std::endl;
Free (p); } void* operator new (size_t size, const std::nothrow_t& nothrow_value) {std::cout << "global nothrow Opera
Tor New with size: "<< size << Std::endl;
return malloc (size); } void operator Delete (void* p, const std::nothrow_t& nothrow_value) {std::cout << "global nothrow Operato
R delete "<< Std::endl;
Free (p);
//global operator new, if not available, invoke Defalut global version.
Same as: (Static_cast<coperatortest*> (:: operator new (sizeof (coperatortest)));
coperatortest* pop4_0 = static_cast<coperatortest*> (operator new (sizeof (coperatortest)));
Same as::: operator Delete (POP4_0);
operator delete (POP4_0); Std::cout << std:: Endl;
Global no throw operator new, if not available, invoke Defalut global version.
Same as:static_cast<coperatortest*> (:: operator new (sizeof (coperatortest), Std::nothrow));
coperatortest* pop4_1 = static_cast<coperatortest*> (operator new (sizeof (coperatortest), Std::nothrow));
Same as::: operator Delete (pop4_1, std::nothrow);
operator delete (pop4_1, std::nothrow); Std::cout << Std::endl;
Output results:
Attention:
¥. Cannot overload the global placement new, because C + + has already provided the laptop's overload, which is what we usually call the placement new.
¥¥. To invoke the global version, either directly or preceded by a two colon, the global version is invoked (:: operator new (sizeof (coperatortest)) and operator new (sizeof (coperatortest)) Will call the global version, which is not the same as new, the new default overrides the overloaded version of this class, and the only way to invoke the global is by adding a double colon.
¥¥¥. Only Coperatortest::operator new (sizeof (Coperatortest)) invokes the class Coperatortest, Global is not overloaded, and the global default is invoked.
2. Operator New/delete also supports adding custom parameters:
void* operator new (size_t size, args ...);
void operator delete (void* ptr, args ...);
Look at the following example:
Class Coperatortest
{public
:
coperatortest ();
Virtual ~coperatortest ();
void* operator new (size_t size, bool ismyparameter);
void operator Delete (void* P, bool ismyparameter);
void* coperatortest::operator New (size_t size, bool ismyparameter)
{
std::cout << "Coperatortest::add Parameter operator new with size: "<< size <<", and Ismyparameter: "<< ismyparameter << Std::endl ;
return malloc (size);
}
void Coperatortest::operator Delete (void* p, bool ismyparameter)
{
std::cout << "Coperatortest::add Parameter operator delete and ismyparameter: "<< ismyparameter << Std::endl;
Free (p);
}
Call:
Coperatortest::operator new with customized parameter
coperatortest* pop5_0 = static_cast<coperatortest* > (Coperatortest::operator New (sizeof (coperatortest), true);
Coperatortest::operator Delete with customized parameter
coperatortest::operator Delete (pop5_0, true);
Output results:
Or more clearly, the global version of the similar, no longer examples, we experiment it.
Finally, look at the array version of operator new[]/delete[].
The array version is the same as the monomer version principle, you can overload the throw exception, or do not throw exceptions, or custom parameters, simply give an example:
void* coperatortest::operator new[] (size_t size)
{
std::cout << "Coperatortest::operator new[] with size : "<< size << Std::endl;
return malloc (size);
}
void Coperatortest::operator delete[] (void* p)
{
std::cout << "Coperatortest::operator delete[]" < < Std::endl;
Free (p);
}
Call, note that you need to calculate the actual need for the size of space, with the direct use of a similar new a[3], not the same, because new[] secretly help us do a lot of things:
Coperatortest::operator new[]
coperatortest* pop6_0 = static_cast<coperatortest*> (COperatorTest::o Perator new[] (3 * sizeof (coperatortest)));
Coperatortest::operator delete[]
coperatortest::operator delete[] (pop6_0);
Std::cout << Std::endl;
Run Result:
Take a look at placement new[]:
void* coperatortest::operator new[] (size_t size, void* p)
{
std::cout << "coperatortest::p lacement Operator new[] with size: "<< size << Std::endl;
return p;
}
by new[] Invocation, you can also call:static_cast<coperatortest*> (Coperatortest::operator new (3 * sizeof (coperatortest)) directly, Pop7_0 ), but it doesn't seem to make sense.
coperatortest* pop7_0 = static_cast<coperatortest*> (malloc (3 * sizeof (coperatortest)));
coperatortest* pop6_2 = new (POP7_0) coperatortest[3];
Output, additional 4 bytes for storing array information:
The global version is similar to the monomer version placement new, and cannot be customized because C + + itself already provides overloaded versions.
This is what is now simply sorted out about operator New/delete and operator new[]/delete[], and of course there is much more to it than that, especially after the C++14 standard, which is what we are often exposed to, You have new and interesting discoveries, welcome to the exchange.