Clause 52: Write the placement new also write palcement delete
question:
widget* pw=new Widget;
The execution of this statement causes two functions to be used: one is the operator new for allocating memory, and the other is the widget's default constructor. Assuming that the first function call succeeds, the second function throws an exception. In this way, the memory allocation of operator New in the first step must be canceled and restored restored, otherwise it will cause a memory leak, at this time, the customer is not able to return memory, because if the widget constructor throws an exception, PW is not currently assigned, The client has no corresponding pointer to the returned memory, the task of canceling the first step and resuming restored becomes the responsibility of the C + + Run-time system.
The runtime system invokes the corresponding operator delete version of operator New in the first step, provided that it must know which operator delete is invoked:
Normal operator new
void * operator new (std::size_t) throw (std::bad_alloc);
Normal operator Delete
//1, normal signed
void operator delete (void* rawmemory) throw () in the global scope;
2, the class scope of the typical signature
void operator delete (void* rawmemory,std::size_t size) throw ();
However, when we declare an abnormal form of operator new, which is the operator new with additional parameters, then call that operator delete.
Class widget{public
:
...
Static void* operator new (std::size_t,std::ostream& logstream) throw (std::bad_alloc);//non-normal form new
static void operator delete (void* pmemory std::size_t size) throw ()//normal class exclusive Delete
...
};
1, placement new/delete of the proposed
If operator new accepts a parameter other than the size_t that is bound to be, this is called placement new, and a number of placement new versions have one that "accepts a pointer to where the object should be constructed". This placement new has been incorporated into the C + + standard library, and #include <new> can be used to invoke it. The appearance of this operator new is as follows:
void* operator new (std::size_t,void* pmemory) throw ();
Above we have already declared a placement new version of the widget, how to use it. Here's an example to make it easy to understand:
widget* pw=new (Std::cerr) widget;//invokes operator new and passes Cerr as its ostream argument, which leaks memory when the Widget constructor throws an exception
So, if you throw an exception at this point, how to cancel the allocation of operator new and restore the restored, because during the runtime the system can not know how the really called operator new operation, so it can not unassign and restore restored, instead of gain and loss C + + Run-time system looking for " The number and type of arguments are the same as the operator new operator delete. If found, it is the calling object. then the operator delete version of this form of Widget's operator new should be:
void operator Delete (void*,std::ostream&) throw ();
This also leads to the definition of placement Delete, if operator delete accepts extra parameters, it is called placement Delete.
Below we write a class-exclusive operator new, which requires a ostream to be used to log related distribution information while washing a normal form of the class-exclusive operator Delete:
Class widget{public
:
...
Static void* operator new (std::size_t size,std::ostream& logstream) throw (std::bad_alloc);
static void operator Delete (void* pmemory) throw ();
static void operator Delete (void* pmemory,std::ostream& logstream) throw ();
...
};
2, the inheritance of placement new
Class base{public
:
...
Static void* operator new (std::size_t size,std::ostream& logstream) throw (std::bad_alloc);//This new will obscure the normal global form
...
};
base* pb=new base;//error. Because the normal form of operator new is obscured
base* pb=new (std::cerr) base;//correct, invoke the Base's placement new
class Derived:public base{ Public
:
...
Static void* operator new (std::size_t size);
...
};
derived* pd=new (std::clog) derived;//error because the placement new in base is obscured derived* pd=new the
correct
To solve the problem of concealment, we need a base class in our home that contains all the normal forms of new and delete:
Class standardnewdeleteforms{public:static void* operator new (std::size_t size) throw (std::bad_alloc) {Retu
RN:: operator new (size);
} static void Opearator Delete (void* pmemory) throw () {:: operator delete (pmemory); Placement New/delete static void* operator new (std::size_t size,void*ptr) throw () {return:: operator new (size
, PTR);
static void operator delete (void* pmemory,void* ptr) throw () {return:: operator delete (pmemory,ptr); Static void* operator new (std::size_t size,const std::nothrow_t& nt) throw () {return:: operator new (size
, NT);
} static void operator delete (void* pmemory,const std::nothrow_t&nt) throw () {:: operator delete (pmemory);
}
};
Class Widget::p ublic standardnewdeleteforms{public:using standardnewdeleteforms::operator new;
Using Standardnewdeleteforms::operator Delete; Static void* operator new (std::size_t size,std::ostream& logstream) throw (StD::BAD_ALLOC);
static void operator Delete (void* pmemory,std::ostream& logstream) throw (); ...
};
PS:
The resolution of operator New/delete or operator new[]/delete[in C + +: http://blog.csdn.net/hazir/article/details/ 21413833
Summary:
1 When you write a placement operator new, be sure to also thank the corresponding placement operator delete, and if not, the program may have hidden and intermittent memory leaks; br> 2 When you declare placement new and placement Delete, make sure that you do not unconsciously obscure their normal version.