I saw code like this:
void *NewElts = operator new(NewCapacityInBytes);
And matching call explicitly operator delete is used consequent later.
Why do this instead of:
void *NewElts = new char[NewCapacityInBytes];
Why explicit call to operator new and operator delete??
Explicitly calling operator new like that calls the global "raw" operator new. Global operator new returns a raw memory block without calling the object's constructor or any user-defined overloads of new. So basically, global operator new is similar to malloc from C.
So:
// Allocates space for a T, and calls T's constructor,
// or calls a user-defined overload of new.
//
T* v = new T;
// Allocates space for N instances of T, and calls T's
// constructor on each, or calls a user-defined overload
// of new[]
//
T* v = new T[N];
// Simply returns a raw byte array of `sizeof(T)` bytes.
// No constructor is invoked.
//
void* v = ::operator new(sizeof(T));
If you write:
T *p = new T;
That allocates enough memory to hold a T, then constructs the T into it. If you write:
T *p = ::operator new(sizeof(T));
That allocates enough memory to hold a T, but doesn't construct the T. One of the times you might see this is when people are also using placement new:
T *p = ::operator new(sizeof(T)); // allocate memory for a T
new (p) T; // construct a T into the allocated memory
p->~T(); // destroy the T again
::operator delete(p); // deallocate the memory
If you call operator new(bytesize), then you can delete it using delete, whereas if you allocate via new char[bytesize], then you have to match it using delete[], which is an abomination to be avoided wherever possible. This is most likely the root reason to use it.
Use it when you want to allocate a block of "raw" memory and don't want anything constructed in that memory.
There is little practical difference between allocating a block of raw memory and "constructing" an array of chars but using operator new clearly signals your intent to anyone reading the code which is important.
Related
I found the following code while reading placement new operator.
#include <iostream>
using namespace std;
class MyClass {
public:
// Placement new operator
void* operator new (size_t sz, void* v) {
cout << "Placement new invoked" << endl;
return v;
}
~MyClass() {
// Cleanup
}
};
int main()
{
// Create a buffer to store the object
int buffer[16];
cout << "Starting address of my buffer = " << &buffer << endl;
// Create the object. Use placement new
MyClass* obj = new (buffer) MyClass();
cout << "Location of my object = " << obj << endl;
// Don't delete object created with placement delete
// Call the destructor explicitly
obj->~MyClass();
}
I have few questions related to delete object which was created using placement new:
what is the clean up code needs to write in destructor in order to
free memory which was occupied obj in buffer memory.
is it not needed to define placement delete, if yes whether it needs to be inside destructor or outside destructor. If it is outside destructor how it will be called ?
Regular new does two things:
allocate memory for your object
construct your object in that memory space.
Placement new means you manage one of those and the other is managed as before.
You allocate / provide the memory for your object
Constructor is called in that memory space.
The reverse is delete of which the regular delete does the following:
Invoke the destructor of the object to clean-up
Free the memory that was allocated for it.
Note that they are done in reverse order for obvious reasons. You cannot free the memory that contains information about what needs to be cleaned up, unti you have finished using that memory. Whereas in construction you need to get hold of the memory first.
In what you call placement delete but is really the reverse of placement new, you need to perform the first step of destruction but not the second. Thus you call the object's destructor, and then you can free up the memory it uses / use it for something else.
The most common example of usage of placement new is in the implementation of std::vector which requires a contiguous buffer for its data, and which lets you reserve ahead (and if you don't it will probably do it for you). That part allocates the memory but does not construct the objects in it. Thus when they are constructed later, placement new is used.
what is the clean up code needs to write in destructor in order to free memory which was occupied obj in buffer memory
The destructor should just do what any destructor does: clean up any resources managed by the object. In this case, it doesn't manage any resources, so there's no need to do anything.
It shouldn't do anything special according to how the storage for the object itself was allocated. Managing that storage is the job for custom new and delete operators, when required.
is it not needed to define placement delete
No. Placement-new is used to construct an object in storage that you're managing yourself, and it's your responsibility to free that storage yourself. In this case, the storage is automatic, so it's automatically freed when the function exits.
Just as the allocator for placement-new does nothing (just returning the provided pointer to pre-allocated storage), so the corresponding deallocator would do nothing; and so it doesn't exist. You just need to destroy the object by calling its destructor directly, before disposing of the storage yourself.
The first thing to ask is: what are you trying to do? If you
define a placement operator new in a class, then that is the
only operator new which will be found when you write new
MyClass; you must always specify the extra arguments. And in
almost every case where you define a class specific operator
new, you should also define a class specific operator delete;
otherwise the global operator delete function will be called
when you write delete p, and that generally won't work.
If your goal is to systematically require separation of
allocation and initialization, and that is why you are defining
a member operator new, then you can provide a no-op operator
delete; if the constructor of the class can throw, then you'll
also want to provide a placement operator delete, since this is
what will be called if the constructor of a newed object exits
via an exception. There is no other way to call it, however.
When providing placement operator new, you must provide
a default operator delete which does the right thing; and when
providing several operator new for the same type, you need to
memorize somehow in each allocation which one was called, in
order to dispatch in the non-placement operator delete.
And by the way, just allocating a buffer as a local variable
does not guarantee sufficient alignment for anything but the
declared buffer type.
EDIT:
Just an example of what would be needed for the operator
delete functions (which must be members):
void operator delete( void* p ) {}
void operator delete( void* p, void* ) {}
(C++/Win32)
consider the following call:
Object obj = new Object(a,b);
other than allocating the virtual memory needed for an instance of an Object, what else is going on under the hood up there? does the compiler places an explicit call to the constructor of Object?
is there any way to initialize a c++ object dynamically without the use of the keyword new?
If you want to initialize an object in some given memory zone, consider the placement new (see this)
BTW, the ordinary Object* n = new Object(123) expression is nearly equivalent to (see operator ::new)
void* p = malloc(sizeof(Object));
if (!p) throw std::bad_alloc;
Object* n = new (p) Object(123); // placement new at p,
// so invokes the constructor
But the implementation could use some non-malloc compatible allocator, so don't mix new and free!
You can always use malloc instead of new, but don't forget to always couple it with free and not delete.
See also :
What is the difference between new/delete and malloc/free?
In his new book TC++PL4, Stroustrup casts a slightly different light on a once usual practice regarding user-controlled memory allocation and placement new—or, more specifically, regarding the enigmatical "placement delete." In the book's sect. 11.2.4, Stroustrup writes:
The "placement delete" operators do nothing except possibly inform a garbage collector that the deleted pointer is no longer safely derived.
This implies that sound programming practice will follow an explicit call to a destructor by a call to placement delete.
Fair enough. However, is there no better syntax to call placement delete than the obscure
::operator delete(p);
The reason I ask is that Stroustrup's sect. 11.2.4 mentions no such odd syntax. Indeed, Stroustrup does not dwell on the matter; he mentions no syntax at all. I vaguely dislike the look of ::operator, which interjects the matter of namespace resolution into something that properly has nothing especially to do with namespaces. Does no more elegant syntax exist?
For reference, here is Stroustrup's quote in fuller context:
By default, operator new creates its object on the free store. What
if we wanted the object allocated elsewhere?... We can place objects
anywhere by providing an allocator function with extra arguments and
then supplying such extra arguments when using new:
void* operator new(size_t, void* p) { return p; }
void buf = reinterpret_cast<void*>(0xF00F);
X* p2 = new(buf) X;
Because of this usage, the new(buf) X syntax for supplying extra
arguments to operator new() is known as the placement syntax.
Note that every operator new() takes a size as its first argument
and that the size of the object allocated is implicitly supplied.
The operator new() used by the new operator is chosen by the
usual argument-matching rules; every operator new() has
a size_t as its first argument.
The "placement" operator new() is the simplest such allocator. It
is defined in the standard header <new>:
void* operator new (size_t, void* p) noexcept;
void* operator new[](size_t, void* p) noexcept;
void* operator delete (void* p, void*) noexcept; // if (p) make *p invalid
void* operator delete[](void* p, void*) noexcept;
The "placement delete" operators do nothing except possibly inform a
garbage collector that the deleted pointer is no longer safely
derived.
Stroustrup then continues to discuss the use of placement new with arenas. He does not seem to mention placement delete again.
If you don't want to use ::, you don't really have to. In fact, you generally shouldn't (don't want to).
You can provide replacements for ::operator new and ::operator delete (and the array variants, though you should never use them).
You can also, however, overload operator new and operator delete for a class (and yes, again, you can do the array variants, but still shouldn't ever use them).
Using something like void *x = ::operator new(some_size); forces the allocation to go directly to the global operator new instead of using a class specific one (if it exists). Generally, of course, you want to use the class specific one if it exists (and the global one if it doesn't). That's exactly what you get from using void *x = operator new(some_size); (i.e., no scope resolution operator).
As always, you need to ensure that your news and deletes match, so you should only use ::operator delete to delete the memory when/if you used ::operator new to allocate it. Most of the time you shouldn't use :: on either one.
The primary exception to that is when/if you're actually writing an operator new and operator delete for some class. These will typically call ::operator new to get a big chunk of memory, then divvy that up into object-sized pieces. To allocate that big chunk of memory, it typically (always?) has to explicitly specify ::operator new because otherwise it would end up calling itself to allocate it. Obviously, if it specifies ::operator new when it allocates the data, it also needs to specify ::operator delete to match.
First of all: No there isn't.
But what is the type of memory? Exactly, it doesn't have one. So why not just use the following:
typedef unsigned char byte;
byte *buffer = new byte[SIZE];
Object *obj1 = new (buffer) Object;
Object *obj2 = new (buffer + sizeof(Object)) Object;
...
obj1->~Object();
obj2->~Object();
delete[] buffer;
This way you don't have to worry about placement delete at all. Just wrap the whole thing in a class called Buffer and there you go.
EDIT
I thought about your question and tried a lot of things out but I found no occasion for what you call placement delete. When you take a look into the <new> header you'll see this function is empty. I'd say it's just there for the sake of completeness. Even when using templates you're able to call the destructor manually, you know?
class Buffer
{
private:
size_t size, pos;
byte *memory;
public:
Buffer(size_t size) : size(size), pos(0), memory(new byte[size]) {}
~Buffer()
{
delete[] memory;
}
template<class T>
T* create()
{
if(pos + sizeof(T) > size) return NULL;
T *obj = new (memory + pos) T;
pos += sizeof(T);
return obj;
}
template<class T>
void destroy(T *obj)
{
if(obj) obj->~T(); //no need for placement delete here
}
};
int main()
{
Buffer buffer(1024 * 1024);
HeavyA *aObj = buffer.create<HeavyA>();
HeavyB *bObj = buffer.create<HeavyB>();
if(aObj && bObj)
{
...
}
buffer.destroy(aObj);
buffer.destroy(bObj);
}
This class is just an arena (what Stroustrup calls it). You can use it when you have to allocate many objects and don't want the overhead of calling new everytime. IMHO this is the only use case for a placement new/delete.
This implies that sound programming practice will follow an explicit call to a destructor by a call to placement delete.
No it doesn't. IIUC Stroustrup does not mean placement delete is necessary to inform the garbage collector that memory is no longer in use, he means it doesn't do anything apart from that. All deallocation functions can tell a garbage colector memory is no longer used, but when using placement new to manage memory yourself, why would you want a garbage collector to fiddle with that memory anyway?
I vaguely dislike the look of ::operator, which interjects the matter of namespace resolution into something that properly has nothing especially to do with namespaces.
"Properly" it does have to do with namespaces, qualifying it to refer to the "global operator new" distinguishes it from any overloaded operator new for class types.
Does no more elegant syntax exist?
You probably don't ever want to call it. A placement delete operator will be called by the compiler if you use placement new and the constructor throws an exception. Since there is no memory to deallocate (because the pacement new didn't allocate any) all it does it potentially mark the memory as unused.
I was looking at the signature of new operator. Which is:
void* operator new (std::size_t size) throw (std::bad_alloc);
But when we use this operator, we never use a cast. i.e
int *arr = new int;
So, how does C++ convert a pointer of type void* to int* in this case. Because, even malloc returns a void* and we need to explicitly use a cast.
There is a very subtle difference in C++ between operator new and the new operator. (Read that over again... the ordering is important!)
The function operator new is the C++ analog of C's malloc function. It's a raw memory allocator whose responsibility is solely to produce a block of memory on which to construct objects. It doesn't invoke any constructors, because that's not its job. Usually, you will not see operator new used directly in C++ code; it looks a bit weird. For example:
void* memory = operator new(137); // Allocate at least 137 bytes
The new operator is a keyword that is responsible for allocating memory for an object and invoking its constructor. This is what's encountered most commonly in C++ code. When you write
int* myInt = new int;
You are using the new operator to allocate a new integer. Internally, the new operator works roughly like this:
Allocate memory to hold the requested object by using operator new.
Invoke the object constructor, if any. If this throws an exception, free the above memory with operator delete, then propagate the exception.
Return a pointer to the newly-constructed object.
Because the new operator and operator new are separate, it's possible to use the new keyword to construct objects without actually allocating any memory. For example, the famous placement new allows you to build an object at an arbitrary memory address in user-provided memory. For example:
T* memory = (T*) malloc(sizeof(T)); // Allocate a raw buffer
new (memory) T(); // Construct a new T in the buffer pointed at by 'memory.'
Overloading the new operator by defining a custom operator new function lets you use new in this way; you specify how the allocation occurs, and the C++ compiler will wire it into the new operator.
In case you're curious, the delete keyword works in a same way. There's a deallocation function called operator delete responsible for disposing of memory, and also a delete operator responsible for invoking object destructors and freeing memory. However, operator new and operator delete can be used outside of these contexts in place of C's malloc and free, for example.
You confuse new expression with operator new() function. When the former is compiled the compiler among other stuff generates a call to operator new() function and passes size enough to hold the type mentioned in the new expression and then a pointer of that type is returned.
As referenced in this site...
http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10
But i did not find the reason, why we should explicitly call the desturctor?
You can think of it as a call to delete, but since you used placement new, you don't want to use delete, as that would attempt to free the memory. If you wanted it to be called automatically, you could use RAII:
// Could use a templated version, or find an existing impl somewhere:
void destroy_fred(Fred* f) {
f->~Fred();
}
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
boost::shared_ptr<Fred> f(new(p) Fred(), destroy_fred);
// ...
// No need for an explicit destructor, cleaned up even during an exception
}
Normally, newed objects are destructed when delete is called. delete is never called for placement new, so you have to figure out when to destruct the object yourself, and do so explicitly.
You can't call ordinary delete because that would attempt free the memory, which was not allocated with ordinary new, so you call the destructor directly and then handle the underlying memory allocation depending on the architecture you are using.
Normally, an object is created using new, and destroyed when you call delete on the object. However, because 'delete' will also try to free the underlying memory back to the heap, you should never call delete on an object which which was instantiated using placement new.
Nevertheless, (no matter how it was allocated) every object ought to be destroyed (because its destructor might do something important).
Therefore instead of the object's being destroyed using delete, you have to destroy the object yourself, and do so explicitly, by invoking its destructor as shown in the FAQ you cited.
The example from your link:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
...
f->~Fred(); // Explicitly call the destructor for the placed object
}
"placement new" return the memory offset that we provide. Right after new the compiler adds a call to the ctor ("placement new" is a also a trick to explicity call a ctor).
"memory" is allocated in the stack so we can not delete it.
string *ps = new string("Hello ");
The new in the above statement is called new operator which do two things
Call operator new(allocates
necessary memory like malloc) and
Call constructor
on raw memory created by operator
new to initialize
delete ps;
Again delete corresponds to
Destruction of object and
Deallocation of memory(i.e, free)
In c++ user is not allowed to call constructor directly,Placement new is used when you have raw memory allocated by some means and wanted to initialize the bits with constructor.Because the memory allocation process did not happen through operator new, delete cannot deallocate the memory.
void someCode()
{
char memory[sizeof(Fred)];//memory allocated on stack
void* p = memory;
Fred* f = new(p) Fred();//placement new
...
f->~Fred(); // Explicitly call the destructor for the placed object
}