placement new signature - c++

void someCode()
{
char memory[sizeof(Foo)];
void* place = memory;
Foo* f = new(place) Foo();
}
and the signature of new placement operator
void * operator new(size_t, void *p)
{
return p;
}
I don't get how a constructor could be bind to void *p since a constructor doesn't return any values ?
EDIT:
the following code for instance doesn't compile :
struct A{};
void f(void * p)
{
}
int main()
{
f(A());
std::cin.ignore();
}

The problem here is that C++ new is confusing:
there is the operator new, which you can overload and is in charge of allocating raw memory
there is the new expression (such as new A(5)) which under the covers first call the corresponding operator new overload and then performs the construction
Note that you have no say as to how the construction is performed: you supplied the type and the constructor parameters, the language does the rest, and there is no way to change this behavior.
Therefore, when you overload/override operator new, you are only affecting the raw memory allocation. The full syntax of the new expression can clear things up:
new (somepointer) A(5)
^~~~~~~~~~~~~ ^~~~
The first part is the list of arguments passed to operator new, on top of the size of the object (always passed). The second part corresponds to the constructor call. If there is no parameter to be passed to new (apart from the size which you don't control) then the first part may be omitted yielding the typical form new A(5).
You are free to overload new as much as you want, for example:
new (alignof(A)) A(5);
will call an operator new overload accepting a size_t as supplementary argument (representing the necessary alignment for the type):
void* operator new(size_t size, size_t alignment);
note: the first argument (size) is always there.
So, placement new is just a fancy overload in its own right:
void* operator new(size_t, void* p) { return p; }
There is not much interest in such an operator (it does nothing), however it helps maintaining a consistent syntax and allows you a way to specify where to build an object via using the new expression so that it is not necessary to create another syntax to allow such operation.

Constructor called after operator new executed. You posted not equivalent code. Equvalent would be
struct A
{
constructor (void* this);
}
int main ()
{
A a = A::constructor(operator new ());
}
It is not c++, just pceudocode

I think that the source of your confusion is an assumption that new(place) Foo(); is a single operation; it is not. Here is what's going on:
A placement new operator is called to allocate memory
A constructor is called to initialize the allocated memory
The first call needs to return the value (a void*). It is a block of memory suitable to store your object. The second call is a constructor. It gets the value from the placement new operator as its hidden this parameter, and performs its regular initialization tasks on it.

Related

Is new T() equivalent to `mem = operator new(sizeof(T)); new(mem)T`?

Basically, my question is whether the following code is valid.
void* mem = operator new(sizeof(T));
T* instance = new(mem) T;
delete instance;
If it isn’t, I’d be curious to know whether there is a way to split allocation and initialization for an object that is going to be deleted through delete obj;.
This does appear to be valid, as long as T is not an array type, and is not a class with a custom operator delete visible from its scope which is incompatible with the operator new you invoke.
[expr.delete]/2 says the operand of delete may be "a pointer to a non-array object created by a previous new-expression". The new-expression grammar syntax symbol does include the placement new syntax, and [expr.delete] doesn't say the previous new-expression needs to be a non-placement variety. And any new-expression including a placement new is considered to "create" an object.
The operator new allocation function and operator delete deallocation function involved do need to match up. operator new(sizeof(T)) will normally call the global ordinary allocation function, but to be more sure you can write ::operator new(sizeof(T)). The deallocation function is looked up in the scope of class T, so a static operator delete(void*); in a class could break this.
You might want to consider exception safety, though. A straight T* p = ::new T; is actually more equivalent to:
void* mem = ::operator new(sizeof(T));
T* p;
try {
p = ::new(mem) T;
} catch (...) {
::operator delete(mem, sizeof(T));
throw;
}
Your code is given almost exactly in the same form, as an explicit example, in the C++ standard:
21.6.2.3 Non-allocating forms [new.delete.placement]
void* operator new(std::size_t size, void* ptr) noexcept;
Returns: ptr.
Remarks: Intentionally performs no other action.
[ Example: This can be useful for constructing an object at a known
address:
void* place = operator new(sizeof(Something));
Something* p = new (place) Something();
— end example ]
Add a delete, after that, and you get what you wrote in your question.

Overloading a new operator - Shouldn't this code yield an error

I am trying to understand how the operator new can be overloaded and got this from the research I did online.
The new operator overload function takes in a size_t type. However in my main I am calling it using new Dummy(). From my understanding Dummy gets implicitly converted to size_t correct ? then what happens to () after Dummy ? shouldn't that result in an error ?
void* operator new(size_t sz)
{
void* m = malloc(sz);
std::cout<<"User Defined :: Operator new"<<std::endl;
return m;
}
class Dummy
{
public:
Dummy()
{
std::cout<<"Dummy :: Constructor"<<std::endl;
}
~Dummy()
{
std::cout<<"Dummy :: Destructor"<<std::endl;
}
};
int main()
{
Dummy * dummyPtr = new Dummy();
}
There are 2 things involving new keyword:
First you have the new operator, there are different overloads defined by the standard and you can override them or create your new ones. It's responsibility is allocating memory of N size and returning a void* to it. You can even create your own new operator that allocates memory and gets an extra parameter like this:
void* operator new(size_t sz, char x) // x is a placement param
{
std::cout << "User Defined :: Operator new" << std::endl;
return ::operator new(sz); // standard new
}
auto* x = new('*') int(234); // our overload
But wait a second, how does the new operator get the size of the type we want to instantiate??
Our friend the new expression just entered the game!
Think about the new expression like some syntactic sugar for calling the new operator. It has this structure:
new(placement_params) type+initializer
it means that for new int(22) the expression will be new(no placements) int + copy_initializer(22) and it will internally call the new operator passing the size of the type.
New operator will return a void* that points to the memory that it just allocated and the right-size of the new expression will initialize that memory. In this example calling the copy initializer
new is a language construct and not a regular function to it has special syntax and conveniences regarding its usage. There's differences between a new expression and operator new
The following both construct a Dummy but one uses local storage and the other uses dynamic storage. So in both cases Dummy() is part of the constructor call and, in the second case, not tied directly to new.
auto d1 = Dummy();
auto d2 = new Dummy();
Here the new expression both allocates space and constructs the Dummy in that space using the supplied constructor and arguments. The amount of space is determined by the compiler via sizeof Dummy.
When you overload the default operator new, it will use your user-defined function to do the allocation, but not the construction (that is done by the new expression).

Global new operator call syntax

Why the function with this signature
void* operator new (std::size_t size);
Cant be called in code like this
void* mem = new(100);
But rather it must be called like this
void mem = ::operator new(100);
Keyword new and operator new are different things.
Keyword new does:
Call operator new to allocate the memory. It can be overloaded for the type being allocated. Keyword new accepts optional arguments that get passed to operator new, this allows for placement new and non-throwing new syntax, see #include <new>.
Invoke the constructor of the object.
If the constructor throws, invoke the corresponding operator delete to free the memory. Note that if that operator delete is not accessible (not public), then new fails at compile time because operator delete cannot be called if the constructor throws and memory would be lost.
Keyword new cannot be overloaded, it always does these steps. This is operator new from step 1 what can be overloaded, normally along with operator delete from step 3.
In other words, X* p = new X(a, b, c); under the hood does something like (pseudo code):
X* p = static_cast<X*>(X::operator new(sizeof(X))); // 1. allocate memory
try {
p->X(a, b, c); // 2. invoke the constructor
}
catch(...) {
X::operator delete(p); // 3. free the memory if the constructor throw
throw;
}
In the above, if X does not overload its operator new, it is the global ::operator new that gets called. Note that X::operator new is implicitly static if overloaded.
There is a profound syntactical reason for this: placement new. With placement new, you can call a constructor without allocating memory for it. It's syntax is this:
#include <new>
Foo* foo = new(bufferPointer) Foo();
Obviously, part of this is the precise syntax you tried to call ::operator new()...

size_t parameter new operator

I have a point in my mind which I can't figure out about new operator overloading.
Suppose that, I have a class MyClass yet MyClass.h MyClass.cpp and main.cpp files are like;
//MyClass.h
class MyClass {
public:
//Some member functions
void* operator new (size_t size);
void operator delete (void* ptr);
//...
};
//MyClass.cpp
void* MyClass::operator new(size_t size) {
return malloc(size);
}
void MyClass::operator delete(void* ptr) {
free(ptr);
}
//main.cpp
//Include files
//...
int main() {
MyClass* cPtr = new MyClass();
delete cPtr
}
respectively. This program is running just fine. However, the thing I can't manage to understand is, how come new operator can be called without any parameter while in its definition it has a function parameter like "size_t size". Is there a point that I am missing here?
Thanks.
Don't confuse the "new expression" with the "operator new" allocation function. The former causes the latter. When you say T * p = new T;, then this calls the allocation function first to obtain memory and then constructs the object in that memory. The process is loosely equivalent to the following:
void * addr = T::operator new(sizeof(T)); // rough equivalent of what
T * p = ::new (addr) T; // "T * p = new T;" means.
(Plus an exception handler in the event that the constructor throws; the memory will be deallocated in that case.)
The new-expression new MyClass() is basically defined in two steps. First it calls the allocator function, which you have overloaded, to get some allocated memory. It passes the size of the type MyClass to that allocator function, which is why the size_t argument is required. After this, it constructs an object in that allocated memory and returns a pointer to it.
The compiler knows the size of your class. Basically, it's passing sizeof(MyClass) into your new function.

Why does operator delete's signature take two parameters?

I've been reading about overloading new and delete (and related topics like placement new/delete). One thing that is confusing me thus far is that operator delete's standard signature is (at class-scope):
void operator delete(void *rawMemory, std::size_t size) throw();
Delete is called like this:
MyClass* ptr = new MyClass;
delete ptr;
So, how does delete ptr; provide the second parameter for size? Also, can I assume that the MyClass* is implicitly converted to the void* in this circumstance?
Short Answer:
new and delete operators are overloaded at class scope for optimizing allocation for objects of specific class. But there can be special scenarios due to certain beasts like Inheritance which may lead to allocation requests for more than the class size itself,Since the very purpose of new and delete overload is special tuning for objects of size sizeof(Base), nothing larger or smaller, these overloaded operators should forward all other wrong sized memory requests to ::operator new and ::operator delete, to be able to do so, the size parameter needs to be passed as an parameter.
Long Answer:
Consider a Special Scenario:
class Base
{
public:
static void * operator new(std::size_t size) throw(std::bad_alloc);
};
class Derived: public Base
{
//Derived doesn't declare operator new
};
int main()
{
// This calls Base::operator new!
Derived *p = new Derived;
return 0;
}
In the above sample, because of inheritance The derived class Derived inherits the new operator of the Base class. This makes calling operator new in a base class to allocate memory for an object of a derived class possible. The best way for our operator new to handle this situation is to divert such calls requesting the "wrong" amount of memory to the standard operator new, like this:
void * Base::operator new(std::size_t size) throw(std::bad_alloc)
{
if (size != sizeof(Base)) // if size is "wrong," i.e != sizeof Base class
{
return ::operator new(size); // let std::new handle this request
}
else
{
//Our implementation
}
}
While overloading the delete operator, One must also ensure that since class-specific operator new forwards requests of the "wrong" size to ::operator new, One MUST forward "wrongly sized" deletion requests to ::operator delete, Since the original operators are guaranteed to to handle these requests in a standard compliant manner.
So the custom delete operator will be something like this:
class Base
{
public:
//Same as before
static void * operator new(std::size_t size) throw(std::bad_alloc);
//delete declaration
static void operator delete(void *rawMemory, std::size_t size) throw();
void Base::operator delete(void *rawMemory, std::size_t size) throw()
{
if (rawMemory == 0)
{
return; // No-Op is null pointer
}
if (size != sizeof(Base))
{
// if size is "wrong,"
::operator delete(rawMemory); //delegate to std::delete
return;
}
//If we reach here means we have correct sized pointer for deallocation
//deallocate the memory pointed to by rawMemory;
return;
}
};
Further Reading:
The following C++-Faq entry talks about overloading new and delete in a standard compliant way and might be a good read for you:
How should i write iso c++ standard conformant custom new and delete operators?
So, how does delete ptr; provide the second parameter for size?
If pointer type is a class type with a virtual destructor, from dynamic information about object type. If it doesn't have a virtual destructor and pointee type matches pointer type - from compile time information about type size. Otherwise delete ptr is undefined behavior.
It's the compiler's job to remember the size to release when you call delete. For delete ptr;, it will pass sizeof(MyClass), for delete[] ptr; it has to remember the number of MyClass in the array, and pass the correct size. I have absolutely no idea how this oddball corner of the language came to be. I can't think of any other part of the language where the compiler must remember a run-time value for you.