Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return value of placement new

Consider the following C++14 code:

#include <cassert> #include <new> #include <type_traits>  struct NonStandardLayout {     // ... };  int main() {     using T = NonStandardLayout;      std::aligned_storage_t< sizeof(T), alignof(T) > storage;     T *const valid_ptr = new(static_cast<void *>(&storage)) T;      T *const maybe_ptr = reinterpret_cast<T *>(&storage);     assert(maybe_ptr == valid_ptr); // ???      valid_ptr->T::~T();     return 0; } 

Is it guaranteed by the standard that the assert in the example will never fail, for any type T?

Discussion

Looking in the latest standard (http://eel.is/c++draft/), I cannot see any reference to this particular scenario but I have found the following paragraphs that arguably points to the answer 'yes'.

Is it correct of me to think that [expr.new/15] and [new.delete.placement/2] together states that the value of valid_ptr will equal the address of storage, always?

If so, is it true that the reinterpret_cast will yield a pointer to a fully constructed object? Because, [expr.reinterpret.cast/7], [expr.static.cast/13] and [basic.compound/4] together seem to indicate that it should be the case.

From my observations, library implementations of the default allocator seem to cast similar to this and without worry! Is it really safe to cast like this?

How can we be sure that the two pointers will be the same, or can we?

like image 273
godpusti Avatar asked Nov 30 '16 20:11

godpusti


People also ask

What does placement new return?

It is unambiguously specified that the placement new operator returns whatever pointer is passed to it.

What's placement new in C++?

Placement new is a variation new operator in C++. Normal new operator does two things : (1) Allocates memory (2) Constructs an object in allocated memory. Placement new allows us to separate above two things. In placement new, we can pass a preallocated memory and construct an object in the passed memory.

Does placement new call constructor?

A placement new expression first calls the placement operator new function, then calls the constructor of the object upon the raw storage returned from the allocator function.


1 Answers

I'm surprised no one has mentioned this cheap counterexample yet:

struct foo {   static foo f;   // might seem dubious but doesn't violate anything   void* operator new(size_t, void* p) {return &f;} }; 

Demo on Coliru.

Unless a class-specific placement version is called, however, your assertion should hold. Both expressions have to represent the same address as explained in the other answer (the main point being that the standard non-allocating operator new simply returns the pointer argument and the new expression not doing anything fancy), and neither of these is a pointer past the end of some object so, by [expr.eq]/2, they compare equal.

like image 178
Columbo Avatar answered Oct 05 '22 16:10

Columbo