What is the underlying implementation of placement new?

178 Views Asked by At
T *p = ::operator new(sizeof(T));
new (p) T;

I wonder how that syntax is working, given that placement new is declared as:

void* operator new(std::size_t, void*)

The second argument void* seems point to the storage of the object, so how does C++ connect the new (p) T to the void*?

In gcc libsupc++ the implementation is simply:

// Default placement versions of operator new.
_GLIBCXX_NODISCARD inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }

_GLIBCXX_NODISCARD inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }

Is the compiler responsible for translating the syntax new(*T) T to the calling of a placement operator new?

2

There are 2 best solutions below

3
ComicSansMS On BEST ANSWER

Is it compiler's responsibility to translate the syntax new(*T) T to the calling of a placement operator new?

Yes, exactly.

Placement new can not be implemented as a library function, it needs special handling from the compiler anyway. The actual implementation that you saw in the libsupc++ source code can be misleading here, as most of the crucial properties of a placement new call are not reflected by that implementation.

0
Mooing Duck On

Using the regular new expression does two things: it calls the function operator new which allocates memory (but does NOT construct), and then it calls the constructor at that location, to create the object at that memory.

For placement new, the operator new(std::size_t, void*) is a no-op, and just returns the pointer that was passed in, and then the compiler calls the constructor at that location, to create the object at that memory.

//normal version                   calls these two functions
MyClass* pMemory = new MyClass;    void* pMemory = operator new(sizeof(MyClass));
                                   MyClass::MyClass(pMemory); //pseudo-syntax

You can also make your own custom new methods, which also work with this same general mechanism.

void* operator new(std::size_t, const char* name) {
    return get_memory_by_name(name);
}

const char* allocation_name = "complex_float";
std::complex<float>* c = new(allocation_name) std::complex<float>{};