当前位置:网站首页>40000 word Wenshuo operator new & operator delete
40000 word Wenshuo operator new & operator delete
2022-07-05 19:27:00 【GarryLau】
1.new
and delete
How it works
C++ Allows you to redefine how memory is allocated and released in your program , It can be at the global level or at the class level . When you need to write a memory pool allocator, you can use this technology . Pair at class level operator new
and operator delete
Reloading is valuable , But don't show off your skills at the overall level .
new
The expression andoperator new
function
Standard library functionsoperator new
andoperator delete
Your name is easily misunderstood . And otheroperator
Functions are different ( such asoperator=
), The two functions are not overloadednew
Expression ordelete
expression .
actually , We simply cannot customizenew
Expression ordelete
The behavior of an expression .
Can overloadoperator new
andoperator delete
To control the allocation and release of memory , But it can't overloadnew
Expression anddelete
expression . in other words , What you can customize is the actual memory allocation and release , But you can't customize the call of constructor and destructor .
We offer newoperator new
Functions andoperator delete
The purpose of the function is to change the way memory is allocated , But anyway , Can't changenew
Operators anddelete
The basic meaning of the operator .
One
new
The execution of expressions is always divided into three steps :
new
Expression calls aoperator new
( oroperator new[]
) The standard library function of , This function allocates a large enough 、 The original 、 Unnamed memory space to store specific types of objects ( Or an array of objects );- The compiler runs the corresponding constructors to construct these objects , And pass in the initial value for it ;
- Object is allocated space and constructed , Returns a pointer to the object .
// new expression std::string *sp = new std::string("a value"); // Assign and initialize a std::string object std::string *arr = new std::string[10]; // Distribute 10 A default initialization std::string object
One
delete
The expression execution process is always divided into two steps :
Execute the corresponding destructor on the object or object array ;
The compiler call is calledoperator delete
oroperator delete[]
To free up memory space .// delete expression delete sp; // The destruction *sp, Then release sp Memory space pointed to delete [] arr; // Destroy the elements in the array , Then release the corresponding memory space
2. The standard library defines operator new
and operator delete
The standard library defines 6 There are different forms of new
expression , Each form has a corresponding operator new
.
Only 2 Species form delete
Expressions can call :delete
and delete[]
, No, nothrow
and placement
In the form of . However, there are 6 Species form operator delete
.
Different compilers ( Tool chain ) Yes operator new
and operator delete
The number and form of implementation are different , Therefore, please check for specific compilers ( Tool chain ) The concrete realization of .
With Visual Studio 2017 To show the standard library right operator new
and operator delete
The definition of , chart 1 It's version information :
Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\Linux\include\usr\include\c++\5\new
// The -*- C++ -*- dynamic memory management header.
// Copyright (C) 1994-2015 Free Software Foundation, Inc.
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file new * This is a Standard C++ Library header. * * The header @c new defines several functions to manage dynamic memory and * handling memory allocation errors; see * http://gcc.gnu.org/onlinedocs/libstdc++/18_support/howto.html#4 for more. */
#ifndef _NEW
#define _NEW
#pragma GCC system_header
#include <bits/c++config.h>
#include <exception>
#pragma GCC visibility push(default)
extern "C++" {
namespace std
{
/** * @brief Exception possibly thrown by @c new. * @ingroup exceptions * * @c bad_alloc (or classes derived from it) is used to report allocation * errors from the throwing forms of @c new. */
class bad_alloc : public exception
{
public:
bad_alloc() throw() {
}
// This declaration is not useless:
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
virtual ~bad_alloc() throw();
// See comment in eh_exception.cc.
virtual const char* what() const throw();
};
#if __cplusplus >= 201103L
class bad_array_new_length : public bad_alloc
{
public:
bad_array_new_length() throw() {
};
// This declaration is not useless:
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
virtual ~bad_array_new_length() throw();
// See comment in eh_exception.cc.
virtual const char* what() const throw();
};
#endif
struct nothrow_t {
};
extern const nothrow_t nothrow;
/** If you write your own error handler to be called by @c new, it must * be of this type. */
typedef void (*new_handler)();
/// Takes a replacement handler as the argument, returns the
/// previous handler.
new_handler set_new_handler(new_handler) throw();
#if __cplusplus >= 201103L
/// Return the current new handler.
new_handler get_new_handler() noexcept;
#endif
} // namespace std
//@{
/** These are replaceable signatures: * - normal single new and delete (no arguments, throw @c bad_alloc on error) * - normal array new and delete (same) * - @c nothrow single new and delete (take a @c nothrow argument, return * @c NULL on error) * - @c nothrow array new and delete (same) * * Placement new and delete signatures (take a memory address argument, * does nothing) may not be replaced by a user's program. */
void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{
return __p; }
inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{
return __p; }
// Default placement versions of operator delete.
inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT {
}
inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT {
}
//@}
} // extern "C++"
#pragma GCC visibility pop
#endif
operator new
There are versions that can throw exceptions ( Default ) And the version that cannot throw exceptions . It should be noted that ,nothrow new
Not throwing exceptions only applies to memory allocation , Subsequent constructor calls may still throw exceptions
Similar to destructors ,operator delete
It is not allowed to throw exceptions . When overloading operator delete
Must be used in different versions of noexcept
The exception specifier specifies that it does not throw an exception .C++ The standard points out from delete
The behavior of throwing an exception is undefined .
about operator new
Function or operator new[]
In terms of functions , The return type must be void*
, The first formal parameter type must be size_t
And the formal parameter cannot contain default arguments . When the compiler calls operator new
when , Pass the number of bytes required to store objects of the specified type to size_t
Shape parameter ; When calling operator new[]
when , The space required to store all elements of the array is passed into the function .
3. heavy load operator new
and operator delete
There will also be a hidden effect similar to the constructor
When the custom implementation overloads the exception version void* operator new(size_t size)
Or do not throw abnormal versions void* operator new(size_t size, const std::nothrow_t&) noexcept
At one of , Compilers will hide the version of the standard library , That is, the compiler will replace the version of the standard library with the customized version . This is similar to hiding the default constructor when you write your own constructor in the class . Suppose that for the above two prototypes, one form is overloaded, but the other form is actually used , The compiler will report an error . Therefore, you can only use which version you overload .
This is true for the impact between the versions of a single element and the impact between the versions of an array , But there is no such effect between the single element version and the array version . See the example in the following small chapter for details . Because the runtime treats operator new
and operator delete
Time is different , Heavy duty operator new
Basically, they can be actively invoked , But overloaded operator delete
Under normal circumstances, only prototypes can be called void operator delete(void* ptr) noexcept
Version of , chapter 4 Will further introduce .
3.1 Single element , Overload throw exception version , No overloading, no throwing exception version , but Attempt Use the version without throwing exceptions
Be careful , This article only discusses the customized version operator new
and operator delete
How to use , Don't discuss operator new
and operator delete
Function implementation details . Therefore, the code examples in this article do not follow some conventions , such as operator new
Should contain a loop , Repeatedly call a new handler
. See references 3 Terms 49 And terms 51
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 1, Single element , Throw an exception version , Start ****************************************************************/
void* operator new(size_t size){
std::cout << "index 1, \"void* operator new(size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete(void* ptr) noexcept {
std::cout << "index 1, \"void operator delete(void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Single element , Throw an exception version , end ****************************************************************/
};
auto main() -> void {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p2 = new(std::nothrow) MyMemory(); // [ERROR] error: no matching function for call to 'test_operator_new::MyMemory::operator new(sizetype, const std::nothrow_t&)'
delete p2;
p2 = nullptr;
std::cout << "------------------------------" << std::endl;
}
}
3.2 Single element , Do not overload throw exception version , Overload does not throw exception version , but Attempt Use exception throwing version
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
//virtual ~MyMemory(){
// std::cout << "MyMemory dtor called." << std::endl;
//}
/* Indexes 2, Single element , Do not throw exception version , Start ****************************************************************/
void* operator new(size_t size, const std::nothrow_t&) noexcept {
std::cout << "index 2, \"void* operator new(size_t size, const std::nothrow_t&) noexcept\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
return nullptr;
}
}
void operator delete(void* ptr, const std::nothrow_t&) noexcept {
std::cout << "index 2, \"void operator delete(void* ptr, const std::nothrow_t&) noexcept\" called.\n";
free(ptr);
}
/* Single element , Do not throw exception version , end ****************************************************************/
};
auto main() -> void {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p2 = new MyMemory(); // [ERROR] error: no matching function for call to 'test_operator_new::MyMemory::operator new(sizetype)'
delete p2; // [ERROR] error: no suitable 'operator delete' for 'test_operator_new::MyMemory'
p2 = nullptr;
std::cout << "------------------------------" << std::endl;
}
}
The above code is better than the chapter 3.1 Many more delete p2;
Error reporting at , This is because the compiler defaults to calling void operator delete(void* ptr) noexcept
Formal operator delete
, Even if overloaded void* operator new(size_t size, const std::nothrow_t&) noexcept
. In Chapter 4 Will further elaborate .
Note that in the example code, in order to clearly show the compilation errors caused by hidden reasons, the destructor virtual ~MyMemory(){std::cout << "MyMemory dtor called." << std::endl;}
Commented out . Because not commenting out will add another error , See chapter for details 4.
3.3 Array , Overload throw exception version , No overloading, no throwing exception version , but Attempt Use the version without throwing exceptions
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 3, Array , Throw an exception version , Start ****************************************************************/
void* operator new[](size_t size) {
std::cout << "index 3, \"void* operator new[](size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete[](void* ptr) noexcept {
std::cout << "index 3, \"void operator delete[](void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Array , Throw an exception version , end ****************************************************************/
};
auto main() -> void {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p1 = new(std::nothrow) MyMemory[2]; // [ERROR] error: no matching function for call to 'test_operator_new::MyMemory::operator new [](sizetype, const std::nothrow_t&)'
delete [] p1;
p1 = nullptr;
std::cout << "------------------------------" << std::endl;
}
}
3.4 Array , Do not overload throw exception version , Overload does not throw exception version , but Attempt Use exception throwing version
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 4, Array , Do not throw exception version , Start ****************************************************************/
void* operator new[](size_t size, const std::nothrow_t&) noexcept {
std::cout << "index 4, \"void* operator new[](size_t size, const std::nothrow_t&) noexcept\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
return nullptr;
}
}
void operator delete[](void* ptr, const std::nothrow_t&) noexcept {
std::cout << "index 4, \"void operator delete[](void* ptr, const std::nothrow_t&) noexcept\" called.\n";
free(ptr);
}
/* Array , Do not throw exception version , end ****************************************************************/
};
auto main() -> void {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p1 = new MyMemory[2]; // [ERROR] error: no matching function for call to 'test_operator_new::MyMemory::operator new [](sizetype)'
delete [] p1; // [ERROR] error: no suitable 'operator delete []' for 'test_operator_new::MyMemory'
p1 = nullptr;
std::cout << "------------------------------" << std::endl;
}
}
3.5 Overloading of a single element version does not affect overloading of an array version
Exception thrown by single element version 、 Do not throw exceptions and array versions throw exceptions 、 There are many combinations that do not throw exceptions , Explain the others in two possible combinations should similar , Not much enumeration .
3.5.1 Overloaded the exception throwing version of a single element , No throw exception version without overloading a single element , It does not affect the use of array version exception throwing version and exception throwing version .
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 1, Single element , Throw an exception version , Start ****************************************************************/
void* operator new(size_t size){
std::cout << "index 1, \"void* operator new(size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete(void* ptr) noexcept {
std::cout << "index 1, \"void operator delete(void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Single element , Throw an exception version , end ****************************************************************/
};
auto main() -> void {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p1 = new MyMemory[2];
delete [] p1;
p1 = nullptr;
std::cout << "++++++++++\n";
MyMemory *p2 = new(std::nothrow) MyMemory[2];
delete [] p2;
p2 = nullptr;
std::cout << "------------------------------" << std::endl;
}
}
Output ( The array version uses the version of the standard library ):
testing operator new & operator delete...
MyMemory ctor called.
MyMemory ctor called.
MyMemory dtor called.
MyMemory dtor called.
++++++++++
MyMemory ctor called.
MyMemory ctor called.
MyMemory dtor called.
MyMemory dtor called.
------------------------------
The end.
3.5.2 Do not overload the exception throwing version of the array , Overload the non throwing exception version of the array , It does not affect the use of exception throwing and exception free versions of a single element
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 4, Array , Do not throw exception version , Start ****************************************************************/
void* operator new[](size_t size, const std::nothrow_t&) noexcept {
std::cout << "index 4, \"void* operator new[](size_t size, const std::nothrow_t&) noexcept\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
return nullptr;
}
}
void operator delete[](void* ptr, const std::nothrow_t&) noexcept {
std::cout << "index 4, \"void operator delete[](void* ptr, const std::nothrow_t&) noexcept\" called.\n";
free(ptr);
}
/* Array , Do not throw exception version , end ****************************************************************/
};
auto main() -> void {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p1 = new MyMemory();
delete p1;
p1 = nullptr;
std::cout << "++++++++++\n";
MyMemory *p2 = new(std::nothrow) MyMemory();
delete p2;
p2 = nullptr;
std::cout << "------------------------------" << std::endl;
}
}
Output :
testing operator new & operator delete...
MyMemory ctor called.
MyMemory dtor called.
++++++++++
MyMemory ctor called.
MyMemory dtor called.
------------------------------
The end.
4. Under normal circumstances , Destructors only call prototypes that are void operator delete(void* ptr) noexcept
Of operator delete
The other version is right operator delete
When is the overload of called ? See 4.3 Small chapters .
4.1 void operator delete(void* ptr) noexcept
Must be a pet
Example of a single element version :
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 1, Single element , Throw an exception version , Start ****************************************************************/
void* operator new(size_t size){
std::cout << "index 1, \"void* operator new(size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete(void* ptr) noexcept {
std::cout << "index 1, \"void operator delete(void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Single element , Throw an exception version , end ****************************************************************/
/* Indexes 2, Single element , Do not throw exception version , Start ****************************************************************/
void* operator new(size_t size, const std::nothrow_t&) noexcept {
std::cout << "index 2, \"void* operator new(size_t size, const std::nothrow_t&) noexcept\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
return nullptr;
}
}
void operator delete(void* ptr, const std::nothrow_t&) noexcept {
std::cout << "index 2, \"void operator delete(void* ptr, const std::nothrow_t&) noexcept\" called.\n";
free(ptr);
}
/* Single element , Do not throw exception version , end ****************************************************************/
};
auto main() -> void {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p1 = new MyMemory();
delete p1;
p1 = nullptr;
std::cout << "++++++++++\n";
MyMemory *p2 = new(std::nothrow) MyMemory();
delete p2; // Note that :index 1, "void operator delete(void* ptr) noexcept" called.
p2 = nullptr;
std::cout << "------------------------------" << std::endl;
}
}
Output :
testing operator new & operator delete...
index 1, "void* operator new(size_t size)" called.
MyMemory ctor called.
MyMemory dtor called.
index 1, "void operator delete(void* ptr) noexcept" called.
++++++++++
index 2, "void* operator new(size_t size, const std::nothrow_t&) noexcept" called.
MyMemory ctor called.
MyMemory dtor called.
index 1, "void operator delete(void* ptr) noexcept" called.
------------------------------
The end.
For a single element in the above code operator delete
The exception throwing version and the exception not throwing version have overloads ,p2
The use of memory applications uses the version that does not throw exceptions , But when memory is released, it is not used void operator delete(void* ptr, const std::nothrow_t&) noexcept
, It is void operator delete(void* ptr) noexcept
.
Example of array version :
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() try {
std::cout << "MyMemory ctor called." << std::endl;
//throw std::runtime_error("hahaha...");
}
catch(...) {
std::cout << "Caught MyMemory's exception." << std::endl;
throw std::runtime_error("MyMemory's ctor caught exception.");
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 3, Array , Throw an exception version , Start ****************************************************************/
void* operator new[](size_t size) {
std::cout << "index 3, \"void* operator new[](size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete[](void* ptr) noexcept {
std::cout << "index 3, \"void operator delete[](void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Array , Throw an exception version , end ****************************************************************/
/* Indexes 4, Array , Do not throw exception version , Start ****************************************************************/
void* operator new[](size_t size, const std::nothrow_t&) noexcept {
std::cout << "index 4, \"void* operator new[](size_t size, const std::nothrow_t&) noexcept\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
return nullptr;
}
}
void operator delete[](void* ptr, const std::nothrow_t&) noexcept {
std::cout << "index 4, \"void operator delete[](void* ptr, const std::nothrow_t&) noexcept\" called.\n";
free(ptr);
}
/* Array , Do not throw exception version , end ****************************************************************/
};
auto main() -> int {
std::cout << "testing operator new & operator delete..." << std::endl;
try {
MyMemory *p1 = new MyMemory[2];
delete [] p1;
p1 = nullptr;
}
catch(...) {
std::cout << "Caught exception in main." << std::endl;
// return 1;
}
std::cout << "++++++++++\n";
try {
MyMemory *p2 = new(std::nothrow) MyMemory[2];
delete [] p2; // Call here void operator delete[](void* ptr) noexcept Version of
p2 = nullptr;
}
catch(...) {
std::cout << "Caught exception in main." << std::endl;
return 1;
}
std::cout << "------------------------------" << std::endl;
return 0;
}
}
The above program outputs :
testing operator new & operator delete...
index 3, "void* operator new[](size_t size)" called.
MyMemory ctor called.
MyMemory ctor called.
MyMemory dtor called.
MyMemory dtor called.
index 3, "void operator delete[](void* ptr) noexcept" called.
++++++++++
index 4, "void* operator new[](size_t size, const std::nothrow_t&) noexcept" called.
MyMemory ctor called.
MyMemory ctor called.
MyMemory dtor called.
MyMemory dtor called.
index 3, "void operator delete[](void* ptr) noexcept" called.
------------------------------
The end.
4.2 Just overload operator delete
Then there must be a prototype void operator delete(void* ptr) noexcept
Version of , Otherwise, it cannot be compiled
The following example shows that as long as you reload operator delete
Then there must be a prototype void operator delete(void* ptr) noexcept
Version of , In fact, you must use this version , Even if other versions are overloaded , It's just that overbearing !!!
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
} // [ERROR] error: no suitable 'operator delete' for 'test_operator_new::MyMemory'
/* Indexes 1, Single element , Throw an exception version , Start ****************************************************************/
void* operator new(size_t size){
std::cout << "index 1, \"void* operator new(size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
#if 0
void operator delete(void* ptr) noexcept {
std::cout << "index 1, \"void operator delete(void* ptr) noexcept\" called.\n";
free(ptr);
}
#endif
/* Single element , Throw an exception version , end ****************************************************************/
/* Indexes 2, Single element , Do not throw exception version , Start ****************************************************************/
void* operator new(size_t size, const std::nothrow_t&) noexcept {
std::cout << "index 2, \"void* operator new(size_t size, const std::nothrow_t&) noexcept\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
return nullptr;
}
}
void operator delete(void* ptr, const std::nothrow_t&) noexcept {
std::cout << "index 2, \"void operator delete(void* ptr, const std::nothrow_t&) noexcept\" called.\n";
free(ptr);
}
/* Single element , Do not throw exception version , end ****************************************************************/
};
auto main() -> void {
std::cout << "testing operator new & operator delete..." << std::endl;
// Don't forget delete p The process of : Call destructor 、 Free memory
MyMemory *p1 = new MyMemory();
delete p1; // [ERROR] error: no suitable 'operator delete' for 'test_operator_new::MyMemory'
p1 = nullptr;
std::cout << "++++++++++\n";
MyMemory *p2 = new(std::nothrow) MyMemory();
delete p2; // [ERROR] error: no suitable 'operator delete' for 'test_operator_new::MyMemory'
p2 = nullptr;
std::cout << "------------------------------" << std::endl;
}
}
The above code comments out that the prototype is void operator delete(void* ptr) noexcept
Implementation of version , Error will be reported in compilation , The error is shown in the comment . That is to say, just reload operator delete
, Under normal circumstances, it must be used void operator delete(void* ptr) noexcept
Version of , And... Are used only when the constructor throws an exception operator new
Matching version .
4.3 Don't void* operator new(size_t size, const std::nothrow_t&) noexcept
The version of is decoration ?
void* operator new(size_t size, const std::nothrow_t&) noexcept
The version of is not a decoration , It is only used when the constructor throws an exception .
reference 《C++ Advanced programming ( The first 2 edition )》P594 say ,4 Kind of ( There are std::nothrow_t
And no single element version 、 Array version )nothrow
and placement
Formal operator delete
Only use when the constructor throws an exception . under these circumstances , Match the used when allocating memory before calling the constructor operator new
Of operator delete
Will be called . However , Delete a pointer normally ,delete
Would call operator delete
or operator delete[]
( Never call nothrow
or placement
In the form of ).
4.3.1 Example of a single element version
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() try {
std::cout << "MyMemory ctor called." << std::endl;
throw std::runtime_error("hahaha...");
}
catch(...) {
std::cout << "Caught MyMemory's exception." << std::endl;
throw std::runtime_error("MyMemory's ctor caught exception.");
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 1, Single element , Throw an exception version , Start ****************************************************************/
void* operator new(size_t size){
std::cout << "index 1, \"void* operator new(size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete(void* ptr) noexcept {
std::cout << "index 1, \"void operator delete(void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Single element , Throw an exception version , end ****************************************************************/
/* Indexes 2, Single element , Do not throw exception version , Start ****************************************************************/
void* operator new(size_t size, const std::nothrow_t&) noexcept {
std::cout << "index 2, \"void* operator new(size_t size, const std::nothrow_t&) noexcept\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
return nullptr;
}
}
void operator delete(void* ptr, const std::nothrow_t&) noexcept {
std::cout << "index 2, \"void operator delete(void* ptr, const std::nothrow_t&) noexcept\" called.\n";
free(ptr);
}
/* Single element , Do not throw exception version , end ****************************************************************/
};
auto main() -> int {
std::cout << "testing operator new & operator delete..." << std::endl;
try {
MyMemory *p1 = new MyMemory();
delete p1;
p1 = nullptr;
}
catch(...) {
std::cout << "Caught exception in main." << std::endl;
// return 1;
}
std::cout << "++++++++++\n";
try {
MyMemory *p2 = new(std::nothrow) MyMemory();
delete p2; // This is called void* operator new(size_t size, const std::nothrow_t&) noexcept
p2 = nullptr;
}
catch(...) {
std::cout << "Caught exception in main." << std::endl;
return 1;
}
std::cout << "------------------------------" << std::endl;
return 0;
}
}
Output :
testing operator new & operator delete...
index 1, "void* operator new(size_t size)" called.
MyMemory ctor called.
Caught MyMemory's exception. index 1, "void operator delete(void* ptr) noexcept" called. Caught exception in main. ++++++++++ index 2, "void* operator new(size_t size, const std::nothrow_t&) noexcept" called. MyMemory ctor called. Caught MyMemory's exception.
index 2, "void operator delete(void* ptr, const std::nothrow_t&) noexcept" called.
Caught exception in main.
The end.
4.3.2 Example of array version
#include <new>
#include <cstdlib>
#include <iostream>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() try {
std::cout << "MyMemory ctor called." << std::endl;
throw std::runtime_error("hahaha...");
}
catch(...) {
std::cout << "Caught MyMemory's exception." << std::endl;
throw std::runtime_error("MyMemory's ctor caught exception.");
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 3, Array , Throw an exception version , Start ****************************************************************/
void* operator new[](size_t size) {
std::cout << "index 3, \"void* operator new[](size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete[](void* ptr) noexcept {
std::cout << "index 3, \"void operator delete[](void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Array , Throw an exception version , end ****************************************************************/
/* Indexes 4, Array , Do not throw exception version , Start ****************************************************************/
void* operator new[](size_t size, const std::nothrow_t&) noexcept {
std::cout << "index 4, \"void* operator new[](size_t size, const std::nothrow_t&) noexcept\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
return nullptr;
}
}
void operator delete[](void* ptr, const std::nothrow_t&) noexcept {
std::cout << "index 4, \"void operator delete[](void* ptr, const std::nothrow_t&) noexcept\" called.\n";
free(ptr);
}
/* Array , Do not throw exception version , end ****************************************************************/
};
auto main() -> int {
std::cout << "testing operator new & operator delete..." << std::endl;
try {
MyMemory *p1 = new MyMemory[2];
delete [] p1;
p1 = nullptr;
}
catch(...) {
std::cout << "Caught exception in main." << std::endl;
// return 1;
}
std::cout << "++++++++++\n";
try {
MyMemory *p2 = new(std::nothrow) MyMemory[2];
delete [] p2; // This is called void* operator new(size_t size, const std::nothrow_t&) noexcept
p2 = nullptr;
}
catch(...) {
std::cout << "Caught exception in main." << std::endl;
return 1;
}
std::cout << "------------------------------" << std::endl;
return 0;
}
}
Output :
testing operator new & operator delete...
index 3, "void* operator new[](size_t size)" called.
MyMemory ctor called.
Caught MyMemory's exception. index 3, "void operator delete[](void* ptr) noexcept" called. Caught exception in main. ++++++++++ index 4, "void* operator new[](size_t size, const std::nothrow_t&) noexcept" called. MyMemory ctor called. Caught MyMemory's exception.
index 4, "void operator delete[](void* ptr, const std::nothrow_t&) noexcept" called.
Caught exception in main.
The end.
5. heavy load operator new
and operator delete
Can be defined in the global scope operator new
Functions and operator delete
function ( Contains the version of the requested single element and the version of the array ), They can also be defined as member functions .
When defining the above operator function as a member of a class , They are Implicit static Of , No declaration is required static
( Doing so will not cause errors ). because operator new
Used before object construction and operator delete
Used after the object is destroyed , So these two members (new
and delete
) Static when necessary , And they cannot manipulate any data members of a class .
If assigned ( Release ) The object is a class type
(a) The compiler first looks in the scope of the class and its base class , If this class contains operator new
Member or operator delete
member , Then the corresponding expression will call these members . otherwise ,(b) The compiler looks for matching functions in the global scope , If the compiler finds a user-defined version , Use this version to execute new
Expression or delete
expression .(c ) If not found , The version defined in the standard library is used .
Be sure to pay attention to ,Bjarne Stroustrup say “ Replace Global operator new
and operator delete
It takes courage ”. However, if you persist , Be sure to pay attention to operator new
In the implementation code of new
Make Rehe call , Otherwise, infinite loops will occur .
5.1 The standard library can be overloaded 8 An overloaded example of a function
#include <iostream>
#include <string>
#include <new>
#include <stdio.h>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() try : pstr_(new std::string){
// Using the standard library new
std::cout << "MyMemory ctor called.\n";
}
catch(std::bad_alloc& e) {
std::cerr << "bad_alloc caught in MyMemory's ctor, " << e.what() << std::endl;
throw /*std::bad_alloc()*/;
}
virtual ~MyMemory() {
delete pstr_; // Using the standard library delete
pstr_ = nullptr;
std::cout << "MyMemory dtor called.\n";
}
void reset() {
std::cout << "reseting...\n";
delete pstr_; // Using the standard library delete
pstr_ = new std::string("The reset one."); // Using the standard library new
std::cout << "reset done.\n";
}
void print() {
if(pstr_) std::cout << *pstr_ << std::endl;
}
/* self-define operator new & operator delete, These functions, with or without keywords static All defaults to static */
/*static*/ void* operator new(size_t size) {
std::cout << "in-class self-define operator new called.\n";
return ::operator new(size);
}
/*static*/ void operator delete(void* ptr) noexcept{
std::cout << "in-class self-define operator delete called.\n";
::operator delete(ptr);
}
/*static*/ void* operator new[](size_t size) {
std::cout << "in-class self-define operator new[] called.\n";
return ::operator new[](size);
}
/*static*/ void operator delete[](void* ptr) noexcept{
std::cout << "in-class self-define operator delete[] called.\n";
::operator delete[](ptr);
}
/*static*/ void* operator new(size_t size, const std::nothrow_t&) noexcept{
std::cout << "in-class self-define noexcept version operator new called.\n";
return ::operator new(size, std::nothrow);
}
/*static*/ void operator delete(void* ptr, const std::nothrow_t&) noexcept{
std::cout << "in-class self-define noexcept version operator delete called.\n";
::operator delete(ptr, std::nothrow);
}
/*static*/ void* operator new[](size_t size, const std::nothrow_t&) noexcept{
std::cout << "in-class self-define noexcept version operator new[] called.\n";
return ::operator new[](size, std::nothrow);
}
/*static*/ void operator delete[](void* ptr, const std::nothrow_t&) noexcept{
std::cout << "in-class self-define noexcept version operator delete[] called.\n";
::operator delete[](ptr, std::nothrow);
}
protected:
std::string *pstr_;
};
auto main() -> int {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory mymem;
std::cout << "+++++\n";
MyMemory *pmymem1 = ::new MyMemory(); // Using the standard library new
::delete pmymem1; // Using the standard library delete
//delete pmymem1; // Use in-class self-define delete,
// The runtime will not be because new When using the standard library new To automatically find the corresponding standard library delete,
// Which version do you want to use new and delete Must be manually specified , But it's best to match them one by one , That is, either use the version of the standard library or use the customized version
std::cout << "+++++\n";
MyMemory *pmymem2 = new MyMemory(); // Use in-class self-define new
pmymem2->reset();
pmymem2->print();
delete pmymem2; // Use in-class self-define delete
std::cout << "+++++\n";
MyMemory *pmymem3 = new(std::nothrow) MyMemory[3];
delete [] pmymem3;
std::cout << "------------------------------" << std::endl;
return 0;
}
}
The above program output :
__cplusplus: 201703
testing operator new & operator delete...
MyMemory ctor called.
+++++
MyMemory ctor called.
MyMemory dtor called.
+++++
in-class self-define operator new called.
MyMemory ctor called.
reseting...
reset done.
The reset one.
MyMemory dtor called.
in-class self-define operator delete called.
+++++
in-class self-define noexcept version operator new[] called.
MyMemory ctor called.
MyMemory ctor called.
MyMemory ctor called.
MyMemory dtor called.
MyMemory dtor called.
MyMemory dtor called.
in-class self-define operator delete[] called.
------------------------------
MyMemory dtor called.
The end.
5.2 Overloading is not allowed void* operator new(size_t, void*);
Version of
void* operator new(size_t, void*);
The form of can only be used by the standard library , It can only be used by the standard library , It can only be used by the standard library , Cannot be redefined by users .placement new
( location new) In the form of :
new (place_address) type
new (place_address) type (initializers)
new (place_address) type [size]
new (place_address) type [size] {
braced initializer list}
among place_address
It must be a pointer , At the same time initializers
A is provided in ( It could be empty ) Comma separated list of initial values , This list of initial values will be used to construct the newly assigned object .
When only one pointer type argument is passed in ,placement new Expressions construct objects without allocating memory .
The following experiment shows that this form can be overloaded , However, the operation results do not meet the expectations . The most important thing is that although it can be overloaded void* operator new(size_t, void*);
In the form of , But how to implement the function ? Shallow copy or something ? Unclear . Only know that this function does not allocate any memory ( therefore The following code example is about palcement new
The overload of is wrong ), It simply returns pointer arguments .( Be careful , The internal implementation of the following code is only an example of overloading ).
#include <typeinfo>
#include <iostream>
#include <string>
#include <new>
#include <stdio.h>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() try : pstr_(new std::string){
// Using the standard library new
std::cout << "MyMemory ctor called.\n";
}
catch(std::bad_alloc& e) {
std::cerr << "bad_alloc caught in MyMemory's ctor, " << e.what() << std::endl;
throw /*std::bad_alloc()*/;
}
virtual ~MyMemory() {
delete pstr_; // Using the standard library delete
pstr_ = nullptr;
std::cout << "MyMemory dtor called.\n";
}
void reset() {
std::cout << "reseting...\n";
delete pstr_; // Using the standard library delete
pstr_ = new std::string("The reset one."); // Using the standard library new
std::cout << "reset done.\n";
}
void print() {
if(pstr_) std::cout << *pstr_ << std::endl;
}
/* self-define operator new & operator delete, These functions, with or without keywords static All defaults to static */
/*static*/ void* operator new(size_t size) {
std::cout << "in-class self-define operator new called.\n";
return ::operator new(size);
}
/*static*/ void operator delete(void* ptr) noexcept{
std::cout << "in-class self-define operator delete called.\n";
::operator delete(ptr);
}
/*static*/ void* operator new[](size_t size) {
std::cout << "in-class self-define operator new[] called.\n";
return ::operator new[](size);
}
/*static*/ void operator delete[](void* ptr) noexcept{
std::cout << "in-class self-define operator delete[] called.\n";
::operator delete[](ptr);
}
/*static*/ void* operator new(size_t size, const std::nothrow_t&) noexcept{
std::cout << "in-class self-define noexcept version operator new called.\n";
return ::operator new(size, std::nothrow);
}
/*static*/ void operator delete(void* ptr, const std::nothrow_t&) noexcept{
std::cout << "in-class self-define noexcept version operator delete called.\n";
::operator delete(ptr, std::nothrow);
}
/*static*/ void* operator new[](size_t size, const std::nothrow_t&) noexcept{
std::cout << "in-class self-define noexcept version operator new[] called.\n";
return ::operator new[](size, std::nothrow);
}
/*static*/ void operator delete[](void* ptr, const std::nothrow_t&) noexcept{
std::cout << "in-class self-define noexcept version operator delete[] called.\n";
::operator delete[](ptr, std::nothrow);
}
// 《C++ Primer》P727 say void* operator new(size_t, void*); The version of does not allow redefinition
/*static*/ void* operator new(size_t size, void*ptr) noexcept{
std::cout << "in-class self-define placement operator new called.\n";
return ::operator new(size, ptr);
}
/*static*/ void operator delete(void*ptr, void*p) noexcept{
std::cout << "in-class self-define placement operator delete called.\n";
::operator delete (ptr, p);
}
/*static*/ void* operator new[](size_t size, void*ptr) noexcept{
std::cout << "in-class self-define placement operator new[] called.\n";
return ::operator new[](size, ptr);
}
/*static*/ void operator delete[](void*ptr, void*p) noexcept{
std::cout << "in-class self-define placement operator delete[] called.\n";
::operator delete[](ptr, p);
}
protected:
std::string *pstr_;
};
auto main() -> int {
std::cout << "testing operator new & operator delete..." << std::endl;
std::cout << "+++++\n";
MyMemory *pmymem4 = new(std::nothrow) MyMemory();
MyMemory *pmymem5 = new(pmymem4)MyMemory();
printf("pmymem4 = %p, pmymem5 = %p\n", pmymem4, pmymem5);
pmymem5->reset();
pmymem4->print();
delete pmymem5;
pmymem5 = nullptr;
// pmymem4->print(); // The runtime crashes
printf("pmymem4 = %p, pmymem5 = %p\n", pmymem4, pmymem5);
if(nullptr == pmymem4){
std::cout << "pmymem4 is nullptr.\n";
}
if(nullptr == pmymem5){
std::cout << "pmymem5 is nullptr.\n";
}
std::cout << "------------------------------" << std::endl;
return 0;
}
}
The above program output ( Results and expectations are different ):
__cplusplus: 201703
testing operator new & operator delete...
+++++
in-class self-define noexcept version operator new called.
MyMemory ctor called.
in-class self-define placement operator new called.
MyMemory ctor called.
pmymem4 = 00000264f10727c0, pmymem5 = 00000264f10727c0
reseting...
reset done.
The reset one.
MyMemory dtor called.
in-class self-define operator delete called.
pmymem4 = 00000264f10727c0, pmymem5 = 0000000000000000
pmymem5 is nullptr.
------------------------------
The end.
5.3 Overload other forms operator new
and operator delete
Define operator new
when , You should also define the corresponding with additional parameters operator delete
. But you can't call this with additional parameters by yourself operator delete
, Only when... With additional parameters is used operator new
And this is called only when the constructor of the object throws an exception operator delete
.
#include <iostream>
#include <string>
#include <new>
#include <cstdlib>
namespace test_operator_new {
class MyMemory {
public:
MyMemory() try : pstr_(new std::string){
// Using the standard library new
std::cout << "MyMemory ctor called.\n";
//throw std::runtime_error("ddd");
}
catch(std::bad_alloc& e) {
std::cerr << "bad_alloc caught in MyMemory's ctor, " << e.what() << std::endl;
throw /*std::bad_alloc()*/;
}
virtual ~MyMemory() {
delete pstr_; // Using the standard library delete
pstr_ = nullptr;
std::cout << "MyMemory dtor called.\n";
}
void reset() {
std::cout << "reseting...\n";
delete pstr_; // Using the standard library delete
pstr_ = new std::string("The reset one."); // Using the standard library new
std::cout << "reset done.\n";
}
void print() {
if(pstr_) std::cout << *pstr_ << std::endl;
}
void* operator new(size_t size, int extra) {
std::cout << "in-class self-define operator new (using malloc) called.\n";
if(void *mem = malloc(size)) {
return mem;
}
else{
throw std::bad_alloc();
}
}
void operator delete(void *mem/*, int extra*/) noexcept {
std::cout << "in-class self-define operator delete (using free) called.\n";
free(mem);
}
void* operator new(size_t size, const std::string& debug_info ) {
std::cout << "The following is new debug infomation: " << debug_info << std::endl;
if(void *mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete(void *mem, const std::string& debug_info) noexcept{
std::cout << "The following is delete debug infomation: " << debug_info << std::endl;
free(mem);
}
protected:
std::string *pstr_;
};
auto main() -> int {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *pmem = new(4) MyMemory();
delete pmem;
pmem = nullptr;
MyMemory *pmem1 = new(std::string("Pyramid")) MyMemory();
delete pmem1;
pmem1 = nullptr;
std::cout << "------------------------------" << std::endl;
return 0;
}
}
Output :
__cplusplus: 201703
testing operator new & operator delete...
in-class self-define operator new (using malloc) called.
MyMemory ctor called.
MyMemory dtor called.
in-class self-define operator delete (using free) called.
The following is new debug infomation: Pyramid
MyMemory ctor called.
MyMemory dtor called.
in-class self-define operator delete (using free) called.
------------------------------
The end.
5.4 Define both global and intra class operator new
and operator delete
What's the effect ???
If overloaded at the global level opeator new
and operator delete
Then the version of the standard library will be hidden . It should be noted that the global level cannot even be used namespace
To limit .
If the global hierarchy and classes are overloaded opeator new
when , For class type objects new
Will use the in class version , For other objects, the global hierarchy overload will be used operator new
;
When using global scope characters for class type objects ::
When you get the global level operator new
, Not the standard library version .
If the global hierarchy and classes are overloaded operator delete
when , For class type objects delete
Will use the in class version , For other objects Standard library operator delete
;
When using global scope characters for class type objects ::
What you get is Standard library Version of .
Example :test_global_operator_new.hpp
#pragma once
#include <new>
#include <cstdlib>
#include <iostream>
/* Indexes 1, Single element , Throw an exception version , Start ****************************************************************/
void* operator new(size_t size){
std::cout << "global, index 1, \"void* operator new(size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete(void* ptr) noexcept {
std::cout << "global, index 1, \"void operator delete(void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Single element , Throw an exception version , end ****************************************************************/
auto testGlobalOperatorNewDelete() -> int {
std::cout << "testing global operator new & operator delete..." << std::endl;
int *p1 = ::new int;
// int *p1 = new int; // Like the previous sentence, this sentence calls the overloaded version void* operator new(size_t size)
::delete p1; // Look at the output , Here is the version of the standard library called
p1 = nullptr;
std::cout << "++++++++++\n";
std::cout << "------------------------------" << std::endl;
return 0;
}
test_operator_new.hpp
:
#pragma once
#include <new>
#include <cstdlib>
#include <iostream>
#include "test_global_operator_new.hpp"
namespace test_operator_new {
class MyMemory {
public:
MyMemory() {
std::cout << "MyMemory ctor called." << std::endl;
}
virtual ~MyMemory(){
std::cout << "MyMemory dtor called." << std::endl;
}
/* Indexes 1, Single element , Throw an exception version , Start ****************************************************************/
void* operator new(size_t size){
std::cout << "index 1, \"void* operator new(size_t size)\" called.\n";
if(void* mem = malloc(size)) {
return mem;
}
else {
throw std::bad_alloc();
}
}
void operator delete(void* ptr) noexcept {
std::cout << "index 1, \"void operator delete(void* ptr) noexcept\" called.\n";
free(ptr);
}
/* Single element , Throw an exception version , end ****************************************************************/
};
auto main() -> int {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p1 = new MyMemory();
delete p1;
p1 = nullptr;
std::cout << "++++++++++\n";
MyMemory *p2 = ::new MyMemory();
::delete p2; // Look at the output , Here is the version of the standard library called
p2 = nullptr;
std::cout << "------------------------------" << std::endl;
return 0;
}
}
main.cpp
#include "test_operator_new.hpp"
#include "test_global_operator_new.hpp"
#include <string>
#include <iostream>
int main()
{
std::cout << "__cplusplus: " << __cplusplus << std::endl;
test_operator_new::main();
std::cout << "================================================\n";
testGlobalOperatorNewDelete();
std::cout << "The end." << std::endl;
}
Output :
__cplusplus: 201703
testing operator new & operator delete...
index 1, "void* operator new(size_t size)" called.
MyMemory ctor called.
MyMemory dtor called.
index 1, "void operator delete(void* ptr) noexcept" called.
++++++++++
global, index 1, "void* operator new(size_t size)" called.
MyMemory ctor called.
MyMemory dtor called.
------------------------------
================================================
testing global operator new & operator delete...
global, index 1, "void* operator new(size_t size)" called.
++++++++++
------------------------------
The end.
5.5 Call the destructor explicitly
You can call destructors through objects , Destructors can also be called through pointers or references to objects , This is no different from calling other member functions .
for example :
std::string *sp = new std::string("value");
using namespace std;
sp->~string();
Calling the destructor destroys the object , But it will not free memory , If necessary , You can reuse this space .
6. Explicitly delete / Default operator new
and operator delete
Explicitly deleting or defaulting is not limited to constructors and assignment operators , You can also aim at operator new
.
for example , The following classes are deleted operator new
and operator new[]
, That is to say, this class cannot pass new
or new[]
Dynamic creation .
#include <iostream>
#include <new>
namespace test_operator_new {
class MyMemory {
public:
MyMemory()=default;
virtual ~MyMemory() {
}
void* operator new(size_t size) = delete;
void* operator new[](size_t size) = delete;
};
auto main() -> int {
std::cout << "testing operator new & operator delete..." << std::endl;
MyMemory *p1 = new MyMemory; // error: use of deleted function 'static void* test_operator_new::MyMemory::operator new(size_t)'
MyMemory *p2 = new MyMemory[3]; // error: use of deleted function 'static void* test_operator_new::MyMemory::operator new [](size_t)'
std::cout << "------------------------------" << std::endl;
return 0;
}
}
7. Reference
1.Marc Gregoire, Nicholas A. Solter, Scott J. Kleper. C++ Advanced programming ( The first 2 edition ). tsinghua university press ,2012.(P593-P599)
2. Stanley B. Lippman, Josée Lajoie, Barbara E. Moo. C++ Primer Chinese version ( The first 5 edition ). Electronic industry press ,2013.(P726-P730)
3. Scott Meyers. Effective C++ Improve program and design 55 Specific practices ( The third edition ), Electronic industry press ,2011.(P240,P252)
The article is longer , Mistakes are inevitable 、 Omissions , Please leave a message in the comment area .
If it works for you , Welcome to one button five : give the thumbs-up 、 Comment on 、 Collection 、 Reward 、 Share .
边栏推荐
猜你喜欢
建议收藏,我的腾讯Android面试经历分享
Worthy of being a boss, byte Daniel spent eight months on another masterpiece
2022 the latest big company Android interview real problem analysis, Android development will be able to technology
详解SQL中Groupings Sets 语句的功能和底层实现逻辑
Millimeter wave radar human body sensor, intelligent perception of static presence, human presence detection application
基于FPGA的超声波测距
测试的核心价值到底是什么?
测试外包公司怎么样?
Advanced application of C # language
100million single men and women supported an IPO with a valuation of 13billion
随机推荐
毫米波雷达人体感应器,智能感知静止存在,人体存在检测应用
618“低调”谢幕,百秋尚美如何携手品牌跨越“不确定时代”?
[AI framework basic technology] automatic derivation mechanism (autograd)
众昂矿业:2022年全球萤石行业市场供给现状分析
司空见惯 - 英雄扫雷鼠
Explain in detail the functions and underlying implementation logic of the groups sets statement in SQL
Fundamentals of shell programming (Part 8: branch statements -case in)
How to convert word into PDF? Word to PDF simple way to share!
IBM大面积辞退40岁+的员工,掌握这十个搜索技巧让你的工作效率至上提高十倍
华为让出的高端市场,小米12S靠徕卡能抢到吗?
Postman core function analysis - parameterization and test report
如何在2022年更明智地应用智能合约?
什么是面上项目
使用easyexcel模板导出的两个坑(Map空数据列错乱和不支持嵌套对象)
Is it safe for China Galaxy Securities to open an account? Securities account opening
XaaS 陷阱:万物皆服务(可能)并不是IT真正需要的东西
[performance test] jmeter+grafana+influxdb deployment practice
JAD installation, configuration and integration idea
Talking about fake demand from takeout order
安卓面试宝典,2022Android面试笔试总结