Has anyone here ever used C++'s "placement new"? If so, what for? It looks to me like it would only be useful on memory-mapped hardware.
-
21This is just the information I've been looking for, to call object constructors on boost allocated memory pools. (Hoping these keywords will make it easier for someone to find in future). – Sideshow Bob Sep 14 '11 at 10:19
-
3It is used in [the C++11 Wikipedia article](https://en.wikipedia.org/wiki/C%2B%2B11#Unrestricted_unions) in the constructor of a union. – HelloGoodbye Nov 05 '15 at 10:15
-
1@HelloGoodbye, interesting! In the article you linked, why can't you just do `p = pt` and use assignment operator of `Point` instead of doing `new(&p) Point(pt)` ? I wonder of the differences between the two. Would the former call `operator=` on Point, while the latter calls copy constructor of `Point` ? but I'm still not very clear why one is better than the other. – Andrei-Niculae Petre Nov 28 '18 at 20:29
-
1@Andrei-NiculaePetre I haven't used placement new myself, but I guess you should use it—together with the copy constructor—if you don't currently have an object of that class, otherwise you should use the copy assignment operator. Unless the class is trivial; then it doesn't matter which of them you use. The same thing goes for destruction of the object. Failing to handle this properly for non-trivial classes may very likely lead to strange behavior, and might even cause [undefined behavior](http://timepp.github.io/doc/cpp14/basic.life.html) in some situations. – HelloGoodbye Nov 28 '18 at 23:30
-
1@Andrei-NiculaePetre Actually, I find the [example](https://en.wikipedia.org/w/index.php?title=C%2B%2B11&oldid=869582471#Unrestricted_unions) in the Wikipedia article quite bad, as it just assumes that no prior object exists and that they need to construct one. This is not the case if `U::operator=` has just been called. – HelloGoodbye Nov 28 '18 at 23:44
-
@HelloGoodbye I agree, in wiki article it's equivalent using assignment or placement new. I was still unsure what the difference between the two was and created a simple code to see the differences and I see now placement new similar to std::move() more, it constructs an object in a given place. https://pastebin.com/37mdM0cM and as you said it's useful if you don't have that object already created and you construct it there on the spot, otherwise you could just use assignment. – Andrei-Niculae Petre Nov 30 '18 at 00:33
-
@Andrei-NiculaePetre Placement new works like ordinary new, only that it doesn't allocate any memory. I.e. it also constructs a new object and thus calls a constructor of the class being instantiated. It doesn't have anything to do with `std::move` (although you can still use `std::move` in the constructor). The `=` operator doesn't call any of the constructors and doesn't have anything to do with `std::move` either. – HelloGoodbye Nov 30 '18 at 13:28
-
Recently I have used placement new for my mempool implementation. So basically previously it just returns new address , now it is constructing object and returning address. – Arun Pal May 29 '19 at 07:50
-
1Here's some **excellent** usage demos / examples to illustrate how to use placement new and what it does! https://www.geeksforgeeks.org/placement-new-operator-cpp/ – Gabriel Staples Sep 13 '20 at 03:37
-
112 years late to the party, but placement new allows you to do the equivalent of _copy non-copyable objects_, even when `memcpy()` cannot be used because it may produce undefined behavior because the object type is non-trivially-copyable. See my (super-long) answer I just added here: https://stackoverflow.com/a/63893849/4561887. Placement new is the magical missing piece I've been desperately needing and didn't know how to get previously without `memcpy()` (but that was undefined behavior for my non-trivially-copyable object)! – Gabriel Staples Sep 15 '20 at 02:34
-
The following links give better clarity about using placement new in the context of a union having a class as a member: https://en.cppreference.com/w/cpp/language/union, https://www.stroustrup.com/C++11FAQ.html#unions – Hari May 25 '23 at 08:26
25 Answers
Placement new allows you to construct an object in memory that's already allocated.
You may want to do this for optimization when you need to construct multiple instances of an object, and it is faster not to re-allocate memory each time you need a new instance. Instead, it might be more efficient to perform a single allocation for a chunk of memory that can hold multiple objects, even though you don't want to use all of it at once.
DevX gives a good example:
Standard C++ also supports placement new operator, which constructs an object on a pre-allocated buffer. This is useful when building a memory pool, a garbage collector or simply when performance and exception safety are paramount (there's no danger of allocation failure since the memory has already been allocated, and constructing an object on a pre-allocated buffer takes less time):
char *buf = new char[sizeof(string)]; // pre-allocated buffer
string *p = new (buf) string("hi"); // placement new
string *q = new string("hi"); // ordinary heap allocation
You may also want to be sure there can be no allocation failure at a certain part of critical code (for instance, in code executed by a pacemaker). In that case you would want to allocate memory earlier, then use placement new within the critical section.
Deallocation in placement new
You should not deallocate every object that is using the memory buffer. Instead you should delete[] only the original buffer. You would have to then call the destructors of your classes manually. For a good suggestion on this, please see Stroustrup's FAQ on: Is there a "placement delete"?

- 1
- 1

- 339,232
- 124
- 596
- 636
-
But I would add that generally it's considered obsolete. As far as I know, it hasn't been deprecated because there are good uses for placement new. – Max Lybbert Oct 21 '08 at 20:20
-
60It's not deprecated as you need this feature to effeciently implement container objects (like vector). If you are not building your own container you don't need to use this feature though. – Martin York Oct 21 '08 at 21:19
-
Well, there are a number of possible uses, such as when deserialising parametric, immutable datatypes. – Marcin Oct 21 '08 at 21:47
-
2
-
30It is also very important to remember to #include
, otherwise you might run into some terrible headaches in some platforms that do not automatically recognize placement new – Ramon Zarazua B. Sep 24 '09 at 18:28 -
26Strictly, it's undefined behaviour to call `delete[]` on the original `char` buffer. Using placement `new` has ended the lifetime of the original `char` objects by re-using their storage. If you now call `delete[] buf` the dynamic type of the object(s) pointed to no longer matches their static type so you have undefined behaviour. It is more consistent to use `operator new`/`operator delete` to allocate raw memory inteded for use by placement `new`. – CB Bailey Mar 21 '10 at 15:10
-
What is really useless is allocating arrays with placement syntax, see http://stackoverflow.com/questions/15254/can-placement-new-for-arrays-be-used-in-a-portable-way – mlvljr Mar 21 '10 at 15:12
-
5It is beneficial to distinguish between operator new() and new() operator. the former allocates, while the latter constructs. – Özgür Apr 05 '10 at 18:06
-
36
-
5This a bad example of pre-allocating a buffer. What is shown is a fixed sized header to the buffer being pre-allocated. The buffer still is on the heap. – jyoung May 13 '12 at 18:18
-
I have found it useful to create a new instance of an immutable object in place of an existing object. The copy assignment operator cannot be used in that situation, because the existing object is immutable. (It might be anti-pattern or non-idiomatic, but it worked well for me.) – Mark Vincze Oct 28 '13 at 15:14
-
1
-
18
-
2Using string as an example is the worst you could do because there is a mental conflict for people to understand the string management object and the sequence of bytes that make the content of the string (which are still put on the heap). And not using std:: as prefix makes it worse and keeps the antipattern of "using std" alive and hurting. – Lothar Jul 08 '18 at 12:33
-
1I'd just like to point out that **you can pre-allocate a buffer or memory pool using _static memory allocation_ as well, instead of dynamic memory allocation**. Ex: in a higher scope than where you will use placement new, statically pre-allocate the buffer like this: `char buf[sizeof(string)];` instead of like this: `char *buf = new char[sizeof(string)];`, but _use it in exactly the same way_! Ex: place this string into that memory buffer using "placement new": `string *p = new (buf) string("hi");`. See also the "Placement new" section here: https://en.cppreference.com/w/cpp/language/new. – Gabriel Staples Sep 13 '20 at 03:12
-
Also, to call a destructor manually, just do: `p->~string();`. Or, if you've lost the `p` handle (pointer) somehow, you can call the destructor manually directly on the buffer, **so long as you are sure a valid object is currently sitting inside of it still, and you know its type!**: `((string*)(&buf[0]))->~string();`. – Gabriel Staples Sep 13 '20 at 03:18
-
I've now expounded upon my points above, and many others, in my answer here: https://stackoverflow.com/a/63893849/4561887. – Gabriel Staples Sep 15 '20 at 02:37
-
1Why do you call the destructor when `delete[]` is called to the original buffer? Shouldn't the call destructor must happen before freeing the buffer? – 김선달 May 22 '21 at 11:16
We use it with custom memory pools. Just a sketch:
class Pool {
public:
Pool() { /* implementation details irrelevant */ };
virtual ~Pool() { /* ditto */ };
virtual void *allocate(size_t);
virtual void deallocate(void *);
static Pool *Pool::misc_pool() { return misc_pool_p; /* global MiscPool for general use */ }
};
class ClusterPool : public Pool { /* ... */ };
class FastPool : public Pool { /* ... */ };
class MapPool : public Pool { /* ... */ };
class MiscPool : public Pool { /* ... */ };
// elsewhere...
void *pnew_new(size_t size)
{
return Pool::misc_pool()->allocate(size);
}
void *pnew_new(size_t size, Pool *pool_p)
{
if (!pool_p) {
return Pool::misc_pool()->allocate(size);
}
else {
return pool_p->allocate(size);
}
}
void pnew_delete(void *p)
{
Pool *hp = Pool::find_pool(p);
// note: if p == 0, then Pool::find_pool(p) will return 0.
if (hp) {
hp->deallocate(p);
}
}
// elsewhere...
class Obj {
public:
// misc ctors, dtors, etc.
// just a sampling of new/del operators
void *operator new(size_t s) { return pnew_new(s); }
void *operator new(size_t s, Pool *hp) { return pnew_new(s, hp); }
void operator delete(void *dp) { pnew_delete(dp); }
void operator delete(void *dp, Pool*) { pnew_delete(dp); }
void *operator new[](size_t s) { return pnew_new(s); }
void *operator new[](size_t s, Pool* hp) { return pnew_new(s, hp); }
void operator delete[](void *dp) { pnew_delete(dp); }
void operator delete[](void *dp, Pool*) { pnew_delete(dp); }
};
// elsewhere...
ClusterPool *cp = new ClusterPool(arg1, arg2, ...);
Obj *new_obj = new (cp) Obj(arg_a, arg_b, ...);
Now you can cluster objects together in a single memory arena, select an allocator which is very fast but does no deallocation, use memory mapping, and any other semantic you wish to impose by choosing the pool and passing it as an argument to an object's placement new operator.

- 8,693
- 3
- 36
- 54
-
1Yep. We get fairly clever about that, but it's off-topic for this question. – Don Wakefield Jan 28 '11 at 20:28
-
2@jdkoftinoff do you have any link to an actual code sample? seems pretty interesting for me! – Victor Jan 14 '17 at 10:26
-
@DonWakefield How do you handle alignment in this pool? Shouldn't you pass alignment as an argument to `allocate()` somewhere? – Mikhail Vasilyev Jun 13 '18 at 17:16
-
1@MikhailVasilyev, in a real implementation, you would of course handle that. Example code only. – Don Wakefield Jun 13 '18 at 17:36
-
-
1I don't understand the syntax behind the `misc_pool` member function. Should it be `Pool* misc_pool()` ? – LRDPRDX Dec 03 '22 at 10:37
-
@LRDPRDX, you are correct, and I've made the change. Please note that the entire code sample is just a sketch and will not compile without additional work. – Don Wakefield Dec 03 '22 at 18:49
-
1@DonWakefield, yes, of course, I just thought that maybe I was not aware of some C++ syntax :) – LRDPRDX Dec 05 '22 at 05:30
It's useful if you want to separate allocation from initialization. STL uses placement new to create container elements.

- 53,214
- 7
- 75
- 105
I've used it in real-time programming. We typically don't want to perform any dynamic allocation (or deallocation) after the system starts up, because there's no guarantee how long that is going to take.
What I can do is preallocate a large chunk of memory (large enough to hold any amount of whatever that the class may require). Then, once I figure out at runtime how to construct the things, placement new can be used to construct objects right where I want them. One situation I know I used it in was to help create a heterogeneous circular buffer.
It's certainly not for the faint of heart, but that's why they make the syntax for it kinda gnarly.

- 44,016
- 10
- 73
- 134
-
Hi TED, could you please share more about the solution you have. I'm thinking on a pre-allocated solution but have not got much progress. Thank you in advance! – Viet Mar 22 '10 at 12:38
-
1Well, the actual hetrogenious circular buffer code was really the tricky part to get right. The palcement new looks a little grisly, but by comparison it was no trouble at all. – T.E.D. Mar 23 '10 at 13:40
I've used it to construct objects allocated on the stack via alloca().
shameless plug: I blogged about it here.

- 171,901
- 28
- 288
- 402

- 98,941
- 38
- 226
- 299
-
interesting article, but I'm not sure I understand the advantage of using this over `boost::array`. Can you expand on that a bit? – GrahamS Feb 10 '11 at 11:52
-
boost::array requires the size of the array to be a compile-time constant. This does not have that limitation. – Ferruccio Feb 10 '11 at 12:26
-
2@Ferruccio This is pretty cool, I did notice that your macro is slightly unsafe though, namely size could be an exepression. If x+1 is passed in for example you would expand it to sizeof(type) * x + 1 which would be incorrect. You need to bracket up your macro to make it safer. – Benj Mar 15 '12 at 11:22
-
Using with alloca looks dangerous to me if an exception is thrown as you have to call the destructors on all your objects. – CashCow Apr 12 '13 at 11:13
It's actually kind of required to implement any kind of data structure that allocates more memory than minimally required for the number of elements inserted (i.e., anything other than a linked structure which allocates one node at a time).
Take containers like unordered_map
, vector
, or deque
. These all allocate more memory than is minimally required for the elements you've inserted so far to avoid requiring a heap allocation for every single insertion. Let's use vector
as the simplest example.
When you do:
vector<Foo> vec;
// Allocate memory for a thousand Foos:
vec.reserve(1000);
... that doesn't actually construct a thousand Foos. It simply allocates/reserves memory for them. If vector
did not use placement new here, it would be default-constructing Foos
all over the place as well as having to invoke their destructors even for elements you never even inserted in the first place.
Allocation != Construction, Freeing != Destruction
Just generally speaking to implement many data structures like the above, you cannot treat allocating memory and constructing elements as one indivisible thing, and you likewise cannot treat freeing memory and destroying elements as one indivisible thing.
There has to be a separation between these ideas to avoid superfluously invoking constructors and destructors unnecessarily left and right, and that's why the standard library separates the idea of std::allocator
(which doesn't construct or destroy elements when it allocates/frees memory*) away from the containers that use it which do manually construct elements using placement new and manually destroy elements using explicit invocations of destructors.
- I hate the design of
std::allocator
but that's a different subject I'll avoid ranting about. :-D
So anyway, I tend to use it a lot since I've written a number of general-purpose standard-compliant C++ containers that could not be built in terms of the existing ones. Included among them is a small vector implementation I built a couple decades ago to avoid heap allocations in common cases, and a memory-efficient trie (doesn't allocate one node at a time). In both cases I couldn't really implement them using the existing containers, and so I had to use placement new
to avoid superfluously invoking constructors and destructors on things unnecessary left and right.
Naturally if you ever work with custom allocators to allocate objects individually, like a free list, then you'd also generally want to use placement new
, like this (basic example which doesn't bother with exception-safety or RAII):
Foo* foo = new(free_list.allocate()) Foo(...);
...
foo->~Foo();
free_list.free(foo);
I've used it to create a Variant class (i.e. an object that can represent a single value that can be one of a number of different types).
If all of the value-types supported by the Variant class are POD types (e.g. int, float, double, bool) then a tagged C-style union is sufficient, but if you want some of the value-types to be C++ objects (e.g. std::string), the C union feature won't do, as non-POD datatypes may not be declared as part of a union.
So instead I allocate a byte array that is big enough (e.g. sizeof(the_largest_data_type_I_support)) and use placement new to initialize the appropriate C++ object in that area when the Variant is set to hold a value of that type. (And I manually call the object's destructor beforehand when switching away to a different data type, of course)

- 70,199
- 15
- 131
- 234
-
3Erm, non-POD datatypes **can** be declared within a union, so long as you provide a union ctor - and hey - that ctor _would probably use placement `new`_ to initialise its non-POD subclass. Ref: http://stackoverflow.com/a/33289972/2757035 Reinventing this wheel using an arbitrarily large byte array is an impressive piece of acrobatics but seems wholly unnecessary, So, what have I missed? :) – underscore_d Nov 20 '15 at 00:50
-
9You missed all the versions of C++ before C++11, that in many cases still need to be supported. :) – Jeremy Friesner Nov 23 '15 at 02:33
Head Geek: BINGO! You got it totally - that's exactly what it's perfect for. In many embedded environments, external constraints and/or the overall use scenario forces the programmer to separate the allocation of an object from its initialization. Lumped together, C++ calls this "instantiation"; but whenever the constructor's action must be explicitly invoked WITHOUT dynamic or automatic allocation, placement new is the way to do it. It's also the perfect way to locate a global C++ object that is pinned to the address of a hardware component (memory-mapped I/O), or for any static object that, for whatever reason, must reside at a fixed address.

- 141
- 1
- 3
Placement new is also very useful when serialising (say with boost::serialization). In 10 years of c++ this is only the second case I've needed placement new for (third if you include interviews :) ).

- 641
- 2
- 10
- 19
I think this has not been highlighted by any answer, but another good example and usage for the new placement is to reduce the memory fragmentation (by using memory pools). This is specially useful in embedded and high availability systems. In this last case it's specially important because for a system that has to run 24/365 days it's very important to have no fragmentation. This problem has nothing to do with memory leakage.
Even when a very good malloc implementation is used (or similar memory management function) it's very difficult to deal with fragmentation for a long time. At some point if you don't manage cleverly the memory reservation/release calls you could end up with a lot of small gaps that are difficult to reuse (assign to new reservations). So, one of the solutions that are used in this case is to use a memory pool to allocate before hand the memory for the application objects. After-wards each time you need memory for some object you just use the new placement to create a new object on the already reserved memory.
This way, once your application starts you already have all the needed memory reserved. All the new memory reservation/release goes to the allocated pools (you may have several pools, one for each different object class). No memory fragmentation happens in this case since there will no gaps and your system can run for very long periods (years) without suffering from fragmentation.
I saw this in practice specially for the VxWorks RTOS since its default memory allocation system suffers a lot from fragmentation. So allocating memory through the standard new/malloc method was basically prohibited in the project. All the memory reservations should go to a dedicated memory pool.

- 16,517
- 6
- 42
- 66
It's also useful when you want to re-initialize global or statically allocated structures.
The old C way was using memset()
to set all elements to 0. You cannot do that in C++ due to vtables and custom object constructors.
So I sometimes use the following
static Mystruct m;
for(...) {
// re-initialize the structure. Note the use of placement new
// and the extra parenthesis after Mystruct to force initialization.
new (&m) Mystruct();
// do-some work that modifies m's content.
}

- 23,081
- 7
- 58
- 59
-
1Wouldn't you need to do a corresponding destruction before re-initializing it that way? – Head Geek Apr 05 '13 at 03:17
-
[Edited for spelling] Usually - you do. But sometimes, when you know the class does not allocate memory or other resources (or you deallocated them externally - for example when you use memory pools), you can use this technique. It does guarantee that the v-table pointers are not overwritten. – nimrodm 16 hours ago – nimrodm Apr 06 '13 at 18:54
-
1Even in C, using setting all bits to 0 is only guarantied to produce a representation of 0 for integral types, not other types (null pointer can have a non zero representation). – curiousguy Aug 16 '15 at 14:20
-
@curiousguy - for primitive types you are correct (it will make the program predictable which is an advantage when it comes to debugging). However, C++ datatypes will have their constructor ran (in-place) and will be properly initialized. – nimrodm Aug 16 '15 at 14:27
It is useful if you are building a kernel - where do you place the kernel code you read from disk or the pagetable? You need to know where to jump to.
Or in other, very rare circumstances such as when you have loads of allocated room and want to place a few structures behind each other. They can be packed this way without the need for the offsetof() operator. There are other tricks for that too, though.
I also believe some STL implementations make use of placement new, like std::vector. They allocate room for 2^n elements that way and don't need to always realloc.

- 2,381
- 14
- 16
-
Reducing memory allocations is one primary reason to use it, as well as "tricks" like loading objects off of disk – lefticus Oct 21 '08 at 16:40
-
I don't know of any kernels written in C++; most kernels are written in straight C. – Adam Rosenfield Oct 21 '08 at 16:50
-
8The operating system with which I learned OS basics is written in C++: http://sweb.sourceforge.net – mstrobl Oct 21 '08 at 19:13
I've used it for storing objects with memory mapped files.
The specific example was an image database which processed vey large numbers of large images (more than could fit in memory).

- 94,801
- 28
- 188
- 263
It's used by std::vector<>
because std::vector<>
typically allocates more memory than there are objects
in the vector<>
.

- 7,321
- 3
- 31
- 36
I've used it to create objects based on memory containing messages received from the network.

- 6,274
- 5
- 47
- 67
I've seen it used as a slight performance hack for a "dynamic type" pointer (in the section "Under the Hood"):
But here is the tricky trick I used to get fast performance for small types: if the value being held can fit inside of a void*, I don't actually bother allocating a new object, I force it into the pointer itself using placement new.

- 19,717
- 4
- 46
- 69
-
What does _if the value being held can fit inside of a void*_ mean? Its always possible to assign any pointer type to void*. Can you please show us some example? – anurag86 Oct 20 '15 at 14:06
-
@anurag86: On my 64 bit machine, a `void*` takes 8 bytes. It's a little silly to point an eight-byte `void*` at a one-byte `bool`. But it's entirely possible to actually overlay the `bool` on the `void*`, much like a `union { bool b; void* v }`. You need some way to know that the thing you called a `void*` is actually a `bool` (or a `short`, or a `float`, etc.). The article I linked to describes how to do that. And, to answer the original question, placement `new` is the feature used to create a `bool` (or other type) where a `void*` is expected, (casts are used to later get/modify the value). – Max Lybbert Oct 20 '15 at 16:12
-
@anurag86: It's not the same thing, but you may be interested in tagged pointers ( https://en.wikipedia.org/wiki/Tagged_pointer ). – Max Lybbert Oct 20 '15 at 16:13
It may be handy when using shared memory, among other uses... For example: http://www.boost.org/doc/libs/1_51_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_anonymous_example

- 4,249
- 1
- 32
- 34
Generally, placement new is used to get rid of allocation cost of a 'normal new'.
Another scenario where I used it is a place where I wanted to have access to the pointer to an object that was still to be constructed, to implement a per-document singleton.

- 40,723
- 12
- 105
- 192
The one place I've run across it is in containers which allocate a contiguous buffer and then fill it with objects as required. As mentioned, std::vector might do this, and I know some versions of MFC CArray and/or CList did this (because that's where I first ran across it). The buffer over-allocation method is a very useful optimization, and placement new is pretty much the only way to construct objects in that scenario. It is also used sometimes to construct objects in memory blocks allocated outside of your direct code.
I have used it in a similar capacity, although it doesn't come up often. It's a useful tool for the C++ toolbox, though.

- 6,808
- 1
- 22
- 34
Script engines can use it in the native interface to allocate native objects from scripts. See Angelscript (www.angelcode.com/angelscript) for examples.

- 1,468
- 3
- 14
- 28
See the fp.h file in the xll project at http://xll.codeplex.com It solves the "unwarranted chumminess with the compiler" issue for arrays that like to carry their dimensions around with them.
typedef struct _FP
{
unsigned short int rows;
unsigned short int columns;
double array[1]; /* Actually, array[rows][columns] */
} FP;

- 37,963
- 15
- 156
- 475

- 761
- 4
- 7
Here is the killer use for the C++ in-place constructor: aligning to a cache line, as well as other powers of 2 boundaries. Here is my ultra-fast pointer alignment algorithm to any power of 2 boundaries with 5 or less single-cycle instructions:
/* Quickly aligns the given pointer to a power of two boundary IN BYTES.
@return An aligned pointer of typename T.
@brief Algorithm is a 2's compliment trick that works by masking off
the desired number in 2's compliment and adding them to the
pointer.
@param pointer The pointer to align.
@param boundary_byte_count The boundary byte count that must be an even
power of 2.
@warning Function does not check if the boundary is a power of 2! */
template <typename T = char>
inline T* AlignUp(void* pointer, uintptr_t boundary_byte_count) {
uintptr_t value = reinterpret_cast<uintptr_t>(pointer);
value += (((~value) + 1) & (boundary_byte_count - 1));
return reinterpret_cast<T*>(value);
}
struct Foo { Foo () {} };
char buffer[sizeof (Foo) + 64];
Foo* foo = new (AlignUp<Foo> (buffer, 64)) Foo ();
Now doesn't that just put a smile on your face (:-). I ♥♥♥ C++1x
I have an idea too. C++ does have zero-overhead principle. But exceptions do not follow this principle, so sometimes they are turned off with compiler switch.
Let's look to this example:
#include <new>
#include <cstdio>
#include <cstdlib>
int main() {
struct A {
A() {
printf("A()\n");
}
~A() {
printf("~A()\n");
}
char data[1000000000000000000] = {}; // some very big number
};
try {
A *result = new A();
printf("new passed: %p\n", result);
delete result;
} catch (std::bad_alloc) {
printf("new failed\n");
}
}
We allocate a big struct here, and check if allocation is successful, and delete it.
But if we have exceptions turned off, we can't use try block, and unable to handle new[] failure.
So how we can do that? Here is how:
#include <new>
#include <cstdio>
#include <cstdlib>
int main() {
struct A {
A() {
printf("A()\n");
}
~A() {
printf("~A()\n");
}
char data[1000000000000000000] = {}; // some very big number
};
void *buf = malloc(sizeof(A));
if (buf != nullptr) {
A *result = new(buf) A();
printf("new passed: %p\n", result);
result->~A();
free(result);
} else {
printf("new failed\n");
}
}
- Use simple malloc
- Check if it is failed in a C way
- If it successful, we use placement new
- Manually call the destructor (we can't just call delete)
- call free, due we called malloc
UPD @Useless wrote a comment which opened to my view the existence of new(nothrow), which should be used in this case, but not the method I wrote before. Please don't use the code I wrote before. Sorry.

- 977
- 2
- 17
-
1Surely you could just use [`new(nothrow)`](https://en.cppreference.com/w/cpp/memory/new/nothrow)? – Useless Jan 04 '21 at 17:06
-
@useless actually, you are right here. I even didn't know about `nothrow`. As I see, we can throw my answer to a garbage. Do you think, I should remove the answer? – CPPCPPCPPCPPCPPCPPCPPCPPCPPCPP Jan 04 '21 at 17:10
-
1It's still correct, so I don't see any need to remove it. There's no harm in leaving it along with the comment. – Useless Jan 04 '21 at 17:50
I have one more idea (it is valid for C++11).
Let's look at the following example:
#include <cstddef>
#include <cstdio>
int main() {
struct alignas(0x1000) A {
char data[0x1000];
};
printf("max_align_t: %zu\n", alignof(max_align_t));
A a;
printf("a: %p\n", &a);
A *ptr = new A;
printf("ptr: %p\n", ptr);
delete ptr;
}
With C++11 standard, GCC gives the following output:
max_align_t: 16
a: 0x7ffd45e6f000
ptr: 0x1fe3ec0
ptr
is not aligned properly.
With C++17 standard and further, GCC gives the following output:
max_align_t: 16
a: 0x7ffc924f6000
ptr: 0x9f6000
ptr
is aligned properly.
As I know, C++ standard didn't support over-aligned new before C++17 came, and if your structure has alignment greater than max_align_t
, you can have problems.
To bypass this issue in C++11, you can use aligned_alloc
.
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <new>
int main() {
struct alignas(0x1000) A {
char data[0x1000];
};
printf("max_align_t: %zu\n", alignof(max_align_t));
A a;
printf("a: %p\n", &a);
void *buf = aligned_alloc(alignof(A), sizeof(A));
if (buf == nullptr) {
printf("aligned_alloc() failed\n");
exit(1);
}
A *ptr = new(buf) A();
printf("ptr: %p\n", ptr);
ptr->~A();
free(ptr);
}
ptr
is aligned in this case.
max_align_t: 16
a: 0x7ffe56b57000
ptr: 0x2416000

- 977
- 2
- 17
Has anyone here ever used C++'s "placement new"? If so, what for? It looks to me like it would only be useful on memory-mapped hardware.
It's really useful when needing to copy out (pass as outputs):
- non-copyable objects (ex: where
operator=()
has been automatically deleted because the class contains aconst
member) OR - non-trivially-copyable objects (where using
memcpy()
is undefined behavior)
...from within a function.
This (obtaining these non-copyable or non-trivially-copyable objects from a function) could aid in unit testing that function, by allowing you to see that a certain data object now looks a certain way after being processed by that function, OR it could simply be a part of your normal API for whatever use you see fit. Let's go over these examples and explain in detail what I mean and how "placement new" can be used to solve these problems.
TLDR;
Note: I've tested every single line of code in this answer. It works. It is valid. It does not violate the C++ standard.
Placement new is:
- The replacement in C++ for
=
whenoperator=()
(the assignment operator) is deleted, and you need to "copy" (actually copy-construct) a therefore otherwise non-copyable object into a given memory location. - The replacement in C++ for
memcpy()
when your object is not trivially-copyable, meaning that usingmemcpy()
to copy this non-trivially-copyable object "may be undefined".
Important: a "non-copyable" object is NOT truly non-copyable. It is simply not copyable via the =
operator is all, which is a call to a class's underlying operator=()
overload function. This means that when you do B = C;
, what is actually happening is a call to B.operator=(C);
, and when you do A = B = C;
, what is actually happening is A.operator=(B.operator=(C));
. Therefore, "non-copyable" objects are only copyable via other means, such as via the class's copy constructor, since, again, the class has no operator=()
method. "Placement new" can be used to call any one of the many constructors which may exist in a class in order to construct an object into a desired pre-allocated memory location. Since "placement new" syntax allows for calling any constructor in a class, this includes passing it an existing instance of a class in order to have placement new call a class's copy-constructor to copy-construct a new object from the passed-in object into another place in memory. Copy-constructing one object into another place in memory...is a copy. This action creates a copy of that original object. When done, you CAN have two objects (instances), that are byte-identical, literally byte for byte (depending on your copy constructor's implementation), located in two separate places in memory. That, by definition, is a copy. It just wasn't done using the class's operator=()
method is all.
Therefore, one might define a class as being "non-copyable" if it has no operator=()
method, but it is still very-much copyable, legally, according to the C++ standard and mechanisms provided by C++, safely and without undefined behavior, using its copy constructor and placement new syntax, as demonstrated below.
Reminder: all lines of code below work. You can run much of the code right here, incl. many of the code blocks below, although it may require some commenting/uncommenting blocks of code since it is not cleanly set up into separate examples.
1. What is a non-copyable object?
A non-copyable object cannot be copied with the =
operator (operator=()
function). That's it! It can still be legally copied, however. See the really important note just above.
Non-copyable class Example 1:
Here, copy-constructing is fine, but copying is prohibited since we have explicitly deleted the assignment operator. Trying to do nc2 = nc1;
results in this compile-time error:
error: use of deleted function ‘NonCopyable1& NonCopyable1::operator=(const NonCopyable1&)’
Here's the full example:
#include <stdio.h>
class NonCopyable1
{
public:
int i = 5;
// Delete the assignment operator to make this class non-copyable
NonCopyable1& operator=(const NonCopyable1& other) = delete;
};
int main()
{
printf("Hello World\n");
NonCopyable1 nc1;
NonCopyable1 nc2;
nc2 = nc1; // copy assignment; compile-time error!
NonCopyable1 nc3 = nc1; // copy constructor; works fine!
return 0;
}
Non-copyable class Example 2:
Here, copy-constructing is fine, but copying is prohibited since the class contains a const
member, which can't be written to (supposedly, since there are work-arounds obviously). Trying to do nc2 = nc1;
results in this compile-time error:
error: use of deleted function ‘NonCopyable1& NonCopyable1::operator=(const NonCopyable1&)’ note: ‘NonCopyable1& NonCopyable1::operator=(const NonCopyable1&)’ is implicitly deleted because the default definition would be ill-formed: error: non-static const member ‘const int NonCopyable1::i’, can’t use default assignment operator
Full example:
#include <stdio.h>
class NonCopyable1
{
public:
const int i = 5; // classes with `const` members are non-copyable by default
};
int main()
{
printf("Hello World\n");
NonCopyable1 nc1;
NonCopyable1 nc2;
nc2 = nc1; // copy assignment; compile-time error!
NonCopyable1 nc3 = nc1; // copy constructor; works fine!
return 0;
}
So, if a class is non-copyable, you can NOT do the following to get a copy of it as an output! The line outputData = data;
will cause compilation to fail with the previous error messages shown in the last example just above!
#include <functional>
#include <stdio.h>
class NonCopyable1
{
public:
const int i; // classes with `const` members are non-copyable by default
// Constructor to custom-initialize `i`
NonCopyable1(int val = 5) : i(val)
{
// nothing else to do
}
};
// Some class which (perhaps asynchronously) processes data. You attach a
// callback, which gets called later.
// - Also, this may be a shared library over which you have no or little
// control, so you cannot easily change the prototype of the callable/callback
// function.
class ProcessData
{
public:
void attachCallback(std::function<void(void)> callable)
{
callback_ = callable;
}
void callCallback()
{
callback_();
}
private:
std::function<void(void)> callback_;
};
int main()
{
printf("Hello World\n");
NonCopyable1 outputData; // we need to receive back data through this object
printf("outputData.i (before) = %i\n", outputData.i); // is 5
ProcessData processData;
// Attach a lambda function as a callback, capturing `outputData` by
// reference so we can receive back the data from inside the callback via
// this object even though the callable prototype returns `void` (is a
// `void(void)` callable/function).
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
// NOT ALLOWED SINCE COPY OPERATOR (Assignment operator) WAS
// AUTO-DELETED since the class has a `const` data member!
outputData = data;
});
processData.callCallback();
// verify we get 999 here, NOT 5!
printf("outputData.i (after) = %i\n", outputData.i);
return 0;
}
One solution: memcpy the data into the outputData
. This is perfectly acceptable in C, but not always ok in C++.
Cppreference.com states (emphasis added):
If the objects are potentially-overlapping or not TriviallyCopyable, the behavior of memcpy is not specified and may be undefined.
and:
Notes
Objects of trivially-copyable types that are not potentially-overlapping subobjects are the only C++ objects that may be safely copied withstd::memcpy
or serialized to/from binary files withstd::ofstream::write()
/std::ifstream::read()
.
(https://en.cppreference.com/w/cpp/string/byte/memcpy)
So, let's just be safe and ensure an object is trivially copyable before copying it with memcpy()
. Replace this part above:
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
// NOT ALLOWED SINCE COPY OPERATOR (Assignment operator) WAS
// AUTO-DELETED since the class has a `const` data member!
outputData = data;
});
with this. Notice the usage of memcpy()
to copy out the data this time, and std::is_trivially_copyable
to ensure, at compile time, this type truly is safe to copy with memcpy()
!:
// (added to top)
#include <cstring> // for `memcpy()`
#include <type_traits> // for `std::is_trivially_copyable<>()`
// Attach a lambda function as a callback, capturing `outputData` by
// reference so we can receive back the data from inside the callback via
// this object even though the callable prototype returns `void` (is a
// `void(void)` callable/function).
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
static_assert(std::is_trivially_copyable<NonCopyable1>::value, "NonCopyable1 must "
"be a trivially-copyable type in order to guarantee that `memcpy()` is safe "
"to use on it.");
memcpy(&outputData, &data, sizeof(data));
});
Sample program output now that it can compile & run. It works!
Hello World outputData.i (before) = 5 outputData.i (after) = 999
To be extra safe, however, you should manually call the destructor of the object you're overwriting before overwriting it, like this:
BEST MEMCPY() SOLUTION:
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
static_assert(std::is_trivially_copyable<NonCopyable1>::value, "NonCopyable1 must "
"be a trivially-copyable type in order to guarantee that `memcpy()` is safe "
"to use on it.");
outputData.~NonCopyable1(); // manually call destructor before overwriting this object
memcpy(&outputData, &data, sizeof(data));
});
If the static_assert()
above fails, however, then you shouldn't use memcpy()
. An always-safe and better C++ alternative, therefore, is to use "placement new".
Here, we simply copy-construct data
right into the memory region occupied by outputData
. That's what this "placement new" syntax does for us! It does NOT dynamically allocate memory, like the new
operator normally does. Normally, the new
operator first dynamically allocates memory on the heap and then constructs an object into that memory by calling the object's constructor. However, placement new does NOT do the allocation part. Instead, it simply skips that part and constructs an object into memory at an address you specify! YOU have to be the one to allocate that memory, either statically or dynamically, beforehand, and YOU have to ensure that memory is properly aligned for that object (see alignof
and alignas
and the Placement new example here) (it will be in this case since we explicitly created the outputData
object as an object, calling it's constructor with NonCopyable1 outputData;
), and YOU have to ensure that the memory buffer/pool is large enough to hold the data you are about to construct into it.
So, the generic placement new syntax is this:
// Call`T`'s specified constructor below, constructing it as an object right into
// the memory location pointed to by `ptr_to_buffer`. No dynamic memory allocation
// whatsoever happens at this time. The object `T` is simply constructed into this
// address in memory.
T* ptr_to_T = new(ptr_to_buffer) T(optional_input_args_to_T's_constructor);
In our case, it will look like this, calling the copy constructor of the NonCopyable1
class, which we've already proven repeatedly above is valid even when the assignment/copy operator is deleted:
// copy-construct `data` right into the address at `&outputData`, using placement new syntax
new(&outputData) NonCopyable1(data);
Our final attachCallback
lambda now looks like this, with the placement new syntax in place of memcpy()
. Notice that the check to ensure the object is trivially copyable is no longer required whatsoever.
===> BEST C++ SOLUTION ALL-AROUND--AVOIDS MEMCPY BY COPY-CONSTRUCTING DIRECTLY INTO THE TARGET MEMORY LOCATION USING PLACEMENT NEW: <==== USE THIS! ====
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
outputData.~NonCopyable1(); // manually call destructor before overwriting this object
// copy-construct `data` right into the address at `&outputData`, using placement new syntax
new(&outputData) NonCopyable1(data);
// Assume that `data` will be further manipulated and used below now, but we needed
// its state at this moment in time.
// Note also that under the most trivial of cases, we could have also just called
// out custom constructor right here too, like this. You can call whatever
// constructor you want!
// new(&outputData) NonCopyable1(999);
// ...
});
2. What is a non-trivially-copyable object?
A non-trivially-copyable object may be one which contains virtual methods and things, as this can lead to the class having to track "vee pointers" (vptr
) and "vee tables" (vtbl
s), to point to the proper virtual implementation in memory. Read more about that here: Dr. Dobb's "Storage Layout of Polymorphic Objects". However, even in this case, so long as you're memcpy()
ing from the same process to the same process (ie: within the same virtual memory space), and NOT between processes, and NOT deserializing from disk to RAM, it seems to me that memcpy()
would technically work fine and produce no bugs (and I've proven this in a handful of examples to myself), but it technically seems to be behavior which is not defined by the C++ standard, so therefore it is undefined behavior, so therefore it can't be relied upon 100% from compiler to compiler, and from one version of C++ to the next, so...it is undefined behavior and you shouldn't memcpy()
in that case.
In other words, if the static_assert(std::is_trivially_copyable<NonCopyable1>::value);
check fails above, do NOT use memcpy()
. You must use "placement new" instead!
One way to get that static assert to fail is to simply declare or define a custom copy/assignment operator in your class definition for your NonCopyable1
class, like this:
// Custom copy/assignment operator declaration:
NonCopyable1& operator=(const NonCopyable1& other);
// OR:
// Custom copy/assignment operator definition:
NonCopyable1& operator=(const NonCopyable1& other)
{
// Check for, **and don't allow**, self assignment!
// ie: only copy the contents from the other object
// to this object if it is not the same object (ie: if it is not
// self-assignment)!
if(this != &other)
{
// copy all non-const members manually here, if the class had any; ex:
// j = other.j;
// k = other.k;
// etc.
// Do deep copy of data via any member **pointers**, if such members exist
}
// the assignment function (`operator=()`) expects you to return the
// contents of your own object (the left side), passed by reference, so
// that constructs such as `test1 = test2 = test3;` are valid!
// See this reference, from Stanford, p11, here!:
// http://web.stanford.edu/class/archive/cs/cs106b/cs106b.1084/cs106l/handouts/170_Copy_Constructor_Assignment_Operator.pdf
// MyClass one, two, three;
// three = two = one;
return *this;
}
(For more examples on custom copy constructors, assignment operators, etc, and the "Rule of Three" and "Rule of Five", see my hello world repository and example here.)
So, now that we have a custom assignment operator, the class is no longer trivially copyable, and this code:
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
static_assert(std::is_trivially_copyable<NonCopyable1>::value, "NonCopyable1 must "
"be a trivially-copyable type in order to guarantee that `memcpy()` is safe "
"to use on it.");
outputData.~NonCopyable1(); // manually call destructor before overwriting this object
memcpy(&outputData, &data, sizeof(data));
});
will produce this error:
main.cpp: In lambda function: main.cpp:151:13: error: static assertion failed: NonCopyable1 must be a trivially-copyable type in order to guarantee that `memcpy()` is safe to use on it. static_assert(std::is_trivially_copyable<NonCopyable1>::value, "NonCopyable1 must " ^~~~~~~~~~~~~
So, you MUST/(really should) use "placement new" instead, like this, as previously described above:
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
outputData.~NonCopyable1(); // manually call destructor before overwriting this object
// copy-construct `data` right into the address at `&outputData`, using placement new syntax
new(&outputData) NonCopyable1(data);
});
More on pre-allocating a buffer/memory pool for usage with "placement new"
If you're really just going to use placement new to copy-construct right into a memory pool/shared memory/pre-allocated object space anyway, there's no need to use NonCopyable1 outputData;
to construct a useless instance into that memory that we have to destroy later anyway. Instead, you can just use a memory pool of bytes. The format is like this:
(From: "Placement new" section here: https://en.cppreference.com/w/cpp/language/new)
// within any scope...
{
char buf[sizeof(T)]; // Statically allocate memory large enough for any object of
// type `T`; it may be misaligned!
// OR, to force proper alignment of your memory buffer for your object of type `T`,
// you may specify memory alignment with `alignas()` like this instead:
alignas(alignof(T)) char buf[sizeof(T)];
T* tptr = new(buf) T; // Construct a `T` object, placing it directly into your
// pre-allocated storage at memory address `buf`.
tptr->~T(); // You must **manually** call the object's destructor.
} // Leaving scope here auto-deallocates your statically-allocated
// memory `buf`.
So, in my example above, this statically-allocated output buffer:
// This constructs an actual object here, calling the `NonCopyable1` class's
// default constructor.
NonCopyable1 outputData;
would become this:
// This is just a statically-allocated memory pool. No constructor is called.
// Statically allocate an output buffer properly aligned, and large enough,
// to store 1 single `NonCopyable1` object.
alignas(alignof(NonCopyable1)) uint8_t outputData[sizeof(NonCopyable1)];
NonCopyable1* outputDataPtr = (NonCopyable1*)(&outputData[0]);
and then you'd read the contents of the outputData
object through the outputDataPtr
pointer.
The former method (NonCopyable1 outputData;
) is best if a constructor for this class exists which requires no input parameters you do NOT have access to at the time of the creation of this buffer, and if you only intend to store this one data type into this buffer, whereas the latter uint8_t
buffer method is best if you either A) do NOT have access to all of the input parameters required to even construct the object at the location you need to create this buffer, OR B) if you plan to store multiple data types into this memory pool, perhaps for communicating between threads, modules, processes, etc, in a union-sort of way.
More on C++ and why it makes us jump through these hoops in this case
So, this whole "placement new" thing in C++, and the need for it, took me a lot of study and a long time to wrap my mind around it. After thinking about it, it has occurred to me that the paradigm of C (where I come from) is to manually allocate some memory, then stick some stuff into it. These are intended to be separate actions when dealing with both static and dynamic memory allocation (remember: you can't even set default values for struct
s!). There is no concept of a constructor or destructor, and even getting the behavior of a scope-based destructor which gets automatically called as a variable exits a given scope is a pain-in-the-butt and requires some fancy gcc extension __attribute__((__cleanup__(my_variable)))
magic as I demonstrate in my answer here. Arbitrarily copying from one object to another, however, is super easy. Just copy the objects around! This is contrasted to the paradigm of C++, which is RAII (Resource Acquisition is Initialization). This paradigm focuses on objects being ready for use the instant they are created. To accomplish this, they rely on constructors and destructors. This means that creating an object like this: NonCopyable1 data(someRandomData);
, doesn't just allocate memory for that object, it also calls the object's constuctor and constructs (places) that object right into that memory. It tries to do multiple things in one. So, in C++, memcpy()
and the assignment operator (=
; AKA: operator=()
function) are explicitly more limited by the nature of C++. This is why we have to go through the hoops of this weird "copy-construct my object into a given memory location via placement new" process in C++ instead of just creating a variable and copying stuff into it later, or memcpy()
ing stuff into it later if it contains a const
member, like we would do in C. C++ really tries to enforce RAII, and this is in part how they do it.
You can use std::optional<>::emplace()
instead
As of C++17, you can use std::optional<>
as a wrapper for this too. The modern C++ emplace()
functions of various containers and wrappers do what we manually did above with "placement new" (see also my answer here and the quote about how std::vector<T,Allocator>::emplace_back
"typically uses placement-new to construct the element in-place").
std::optional
statically allocates a buffer large enough for the object you want to put into it. It then either stores that object, or a std::nullopt
(same as {}
), which means it does not hold that object. To replace one object in it with another object, just call the emplace()
method on the std::optional
object. This does the following:
Constructs the contained value in-place. If
*this
already contains a value before the call, the contained value is destroyed by calling its destructor.
So, it first manually calls the destructor on an existing object already inside it, if an existing object is already inside it, then it does the equivalent of "placement new" to copy-construct a new object (which you provide it) into that memory space.
So, this output buffer:
NonCopyable1 outputData;
// OR
alignas(alignof(NonCopyable1)) uint8_t outputData[sizeof(NonCopyable1)];
NonCopyable1* outputDataPtr = (NonCopyable1*)(&outputData[0]);
now becomes this:
# include <optional>
std::optional<NonCopyable1> outputData = std::nullopt;
and this "placement new" copy-constructing into that output buffer:
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
outputData.~NonCopyable1(); // manually call destructor before overwriting this object
// copy-construct `data` right into the address at `&outputData`, using placement new syntax
new(&outputData) NonCopyable1(data);
});
now becomes this emplace()
ment of new data into that buffer. Notice that the manual call to the destructor is no longer necessary since std::optional<>::emplace()
already handles calling the destructor on any already-existing object for us!:
processData.attachCallback([&outputData]()
{
int someRandomData = 999;
NonCopyable1 data(someRandomData);
// emplace `data` right into the `outputData` object
outputData.emplace(data);
});
Now, to get the data out of outputData
, simply dereference it with *
, or call .value()
on it. Ex:
// verify we get 999 here!
if (outputData.has_value())
{
printf("(*outputData).i (after) = %i\n", (*outputData).i);
// OR
printf("outputData.value().i (after) = %i\n", outputData.value().i);
}
else
{
printf("outputData.has_value() is false!");
}
Sample output:
Hello World (*outputData).i (after) = 999 outputData.value().i (after) = 999
Run this full example code here.
References & additional, EXCELLENT reading:
- *****+[some of the most-useful and simplest "placement new" examples Iv'e ever seen!] https://www.geeksforgeeks.org/placement-new-operator-cpp/
- [great example] https://en.cppreference.com/w/cpp/language/new --> see the "Placement new" section and example here! (I helped write the example).
- How do I make this C++ object non-copyable?
- [makes the really important point that calling the placement new line calls the object's constructor as it constructs it!: Line #3 (
Fred* f = new(place) Fred();
) essentially just calls the constructorFred::Fred()
. This means "thethis
pointer in theFred
constructor will be equal toplace
".] http://www.cs.technion.ac.il/users/yechiel/c++-faq/placement-new.html - Dr. Dobb's "Storage Layout of Polymorphic Objects"
- [good pre-C++11 intro to the C++ "Rule of Three"] http://web.stanford.edu/class/archive/cs/cs106b/cs106b.1084/cs106l/handouts/170_Copy_Constructor_Assignment_Operator.pdf
- My "hello world" example and repository, demoing custom copy constructors, assignment operators, etc., related to the C++ "Rule of Three" / "Rule of Five" / "Rule of Zero" / "Rule of 0/3/5": https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/cpp/copy_constructor_and_assignment_operator/copy_constructor_and_assignment_operator.cpp
- [an excellent writeup by Microsoft on the usage of C++17's
std::optional<>
type] https://devblogs.microsoft.com/cppblog/stdoptional-how-when-and-why/ - [related, since "placement new" very clearly solves this problem too, as this problem was the crux of and driving force behind most of my solutions and examples here!] const member and assignment operator. How to avoid the undefined behavior?

- 36,492
- 15
- 194
- 265
-
3The answer is totally misguided. Whether trivially copyable or not, objects are copied by assignment operator, i.e. just `a=b`. If a class is made non-copyable, there is a reason for it, and you should not try copying it. Placement new is unrelated to both cases. – Eugene Sep 16 '20 at 03:24
-
Tell that to the C++11 standards committee who created the `emplace()` methods for the std container types which use placement new to construct objects into memory within a container, including when the object contains a `const` member and has an implicitly auto-deleted assignment operator. Make sure you let them know they are all misguided and should roll back to C++03. – Gabriel Staples Sep 16 '20 at 03:29
-
-
2`emplace()` is used to **construct** objects in a container, not to copy them! Yes, it allows avoiding unneeded copies, including impossible copies.Placement `new` is always used by containers, with or without `emplace()`, and that's an important use - as mentioned in a few other answers to this question. – Eugene Sep 16 '20 at 03:53
-
**Already-constructed** objects can also be passed to `emplace()` methods, in which case `emplace()` **copy-constructs** them into a desired memory location. My answer also shows how to copy-construct an object into a desired memory location, & that is the premise of this answer. I maintain it is correct and shows well-defined, correct usages & behaviors, supported by the C++ standards. C++ supports not only high-level application development, but also low-level embedded systems, where certain memory-level operations must be done. There exist use-cases where what I demonstrate is desirable. – Gabriel Staples Sep 16 '20 at 04:20
-
Yes, `emplace()` can copy-construct if the object is copyable. Neither `emplace()` nor placement `new` can help is an object is non-copyable. Copying non-copyable and non-trivially copyable objects is your TLDR, and this is where your answer differs from others. And, again: copying non-trivially copyable objects is not a problem at all; copying non-copyable objects should not even be attempted. Beyond TLDR, your answer certainly contains a few true statements, but mostly explaining unrelated topics. – Eugene Sep 16 '20 at 04:30
-
@Eugene, that response doesn't make any sense. I've run and tested every bit of code here. Every line. Nothing is non-copyable. Nothing. Literally. It's just memory. Bytes can be copied. That aside, when I say "non-copyable" I mean simply: where you don't have a valid `operator=()` function overload. That's it. Your statement here: `Neither emplace() nor placement new can help is an object is non-copyable`, also makes zero sense, because that's *exactly* what `emplace()` does: it works even when a class has no `operator=()` method, by copy-constructing it into a desired place in memory. – Gabriel Staples Sep 16 '20 at 04:33
-
Copy-constructing into a place in memory...is a copy. When done, you have two objects (instances). They are byte-identical, byte for byte, located in two separate places in memory. That, by definition, is a copy. It just wasn't done using the `operator=()` method is all. – Gabriel Staples Sep 16 '20 at 04:35
-
I've added a couple really important notes to my TLDR section in the answer. – Gabriel Staples Sep 16 '20 at 05:05
-
When C++ was first created, the intention was that C code which didn't need to use the new features of C++ should generally behave as it would have in C. This would strongly imply that constructs that allocate memory and stuff an object there using memcpy or other such means were regarded as having defined behavior. Does any version of the C++ Standard articulate a desire to deprecate such constructs, or are such notions spring from the minds of compiler writers who favor "optimization" over compatibility with existing useful programs? – supercat Sep 16 '20 at 20:15
-
@supercat, it sounds like your comment is in defense of my position, is that correct? What you are saying seems to be defending what I am saying and doing in my answer. – Gabriel Staples Sep 16 '20 at 22:18
-
@GabrielStaples: It sounds like your answer is saying that the C++ Standard does not longer regards as defined constructs that were unambiguously understood as being defined when the Standard was written. I was asking whether any version of the Standard acknowledges such a change, or whether the C++ Standard never accurately describe the C++ language that was already in use when it was written, and that it was chartered to describe. – supercat Sep 16 '20 at 22:35
-
I'm confused what you mean. I'm not going against the C++ standard. My answer demonstrates, in this order: 1) what might cause `operator=()` to no longer be defined, 2) under what conditions `memcpy()` allows you to copy these objects anyway, 3) when you *must* use placement new instead of `memcpy()` to do this instead, 4) that what I just did is how C++11 implements `emplace()` methods which can copy objects where `operator=()` is not defined, 5) that you can use C++17's `std::optional<>::emplace()` method instead, to do what I demo, since it also is implemented by placement new internally. – Gabriel Staples Sep 16 '20 at 22:46
-
@GabrielStaples: As you said, the normal paradigm for C programs is to acquire a chunk of storage by some means and write data to it as though it were an object of whatever type is desired. If C++ was created as an upwardly-compatible variant of C, that would seem to imply that when it was created, that paradigm would be usable in C++ for the same kinds of objects as it was usable in C (though not necessarily for types that only existed in C++). If that paradigm is no longer usable today, that would imply that at some point the Committee made a major breaking change to the language. – supercat Mar 23 '22 at 21:02
-
@GabrielStaples: My suspicion is that the breaking change occurred with a shift in attitude between "there's no need for the Standard to explicitly deal with such cases because everyone knows how they should obviously work" to "the failure of the Standard to mandate support for such constructs should be interpreted as deprecation thereof". – supercat Mar 23 '22 at 21:05