C++ "placement new" intricacies - c++

I've been reading some questions about placement new on SO and I am finding some different ways to use it that I thought I would ask about here. I understand that placement new is basically a way for you to create an object and give it a certain place in memory of your choice that has already been allocated; I just don't understand all of the intricacies.
First one I saw on SO uses this example (from C++ Primer):
const int BUF = 512;
const int N = 5;
char buffer[BUF];
double * pd1;
pd1 = new (buffer) double[N];
Second one I saw on SO uses this example (from C++ Primer Plus):
char * buffer = new char[BUF]; //get a block of memory
JustTesting *pc1, *pc2;
pc1 = new (buffer) JustTesting; //Place object in buffer
The main difference between these two is that in the first block of code, buffer is a char array and in the second example it is a pointer to a char array, yet both blocks of code contain new (buffer).
My first question is: When using placement new in this context, can it accept either an object or it's address, and if so, is one preferred?
I've also seen placement new used without an lvalue. See below.
new(&myObject) myClass;
My second question is: What are the differences between placement new with vs. without an lvalue?

I understand that placement new is basically a way for you to create an object and give it a certain place in memory of your choice that has already been allocated;
Not exactly.
new expression calls the corresponding operator new and then invokes the constructor. Note that these are two different things named similarly.
Placement new expression skips allocating memory and only invokes the constructor. This is achieved by using the placement void* operator new( std::size_t count, void* ptr), which does nothing and returns ptr.
It is your job to provide storage for the object being initialized when using placement new.

Your first question is already answered. For your 2nd question - What are the differences between placement new with vs. without an lvalue?
Since placement new returns the address that is passed in its 2nd parameter, requiring an lvalue to store that address is optional. See the placement new implementation below from Microsoft Visual Studio-
inline void *__CRTDECL operator new(size_t, void *_Where) _THROW0()
{ // construct array with placement at _Where
return (_Where);
}

Related

Why do both pointers have the same memory address?

#include <iostream>
using namespace std;
int main()
{
char* MainBlock = new char[100];
char* SubBlock1 = new (MainBlock) char[20];
char* SubBlock2 = new (MainBlock) char [20];
cout << static_cast<void*>(SubBlock1) << " " << static_cast<void*>(SubBlock2);
}
Why do both the pointers in the code above have the same address? I expected SubBlock2 to be 20 bytes after SubBlock 1.
Does this mean I can allocate an endless number of pointers with placement new even though I only have 100 bytes?
How can I ensure that SubBlock6 will be a nullptr or out of bounds using placement new?
Why do both the pointers in the code above have the same address?
Placement new accepts the exact address where it will initialize the object being created. You pass the same address, you get the same address.
Does this mean I can allocate an endless number of pointers with placement new even though I only have 100 bytes?
No. Each placement new reuses the storage. You can of course reuse the storage infinitely many times, but you will only ever have the same 100 characters allocated at most.
How can I ensure that SubBlock6 will be a nullptr or out of bounds using placement new?
There is no way. The onset is on you to provide valid storage for placement new to create the objects. If you don't, the behavior is undefined.
And finally, you don't need to muck about with placement new.
char *SubBlock1 = MainBlock;
char *SubBlock2 = MainBlock + 20;
Partitions the buffer just fine. Just be sure to delete[] only the pointer value stored in MainBlock.
The (MainBlock) argument is a placement argument. You are in fact explicitly telling the program to allocate both SubBlock1 and SubBlock2 at the address of MainBlock.
Each new expression to get the address at which to construct the object calls the appropriate allocation function. Once the allocation is done and the address is returned from the allocation function, it attempts to construct the object exactly at the specified address.
Given char* SubBlock1 = new (MainBlock) char[20];, it calls the following allocation function:
void* operator new[]( std::size_t count, void* ptr );
Called by the standard array form placement new expression. The standard library implementation performs no action and returns ptr unmodified.
As the documentation above say, calling this allocation function does nothing and returns the address you passed unmodified. So, this new expression constructs 20 char exactly at MainBlock. This is why you get the same address for both SubBlock1 and SubBlock2.
Does this mean I can allocate an endless number of pointers with placement new even though I only have 100 bytes?
No. Note that allocation and construction are two different things. In your example, you allocate the memory only once and construct objects many times on it. So the layout of objects constructed on the allocated memory is up to you.

Overriding new operator - non-allocating placement allocation functions

I am in need to write / overload / override default C++ new operator. I found this below information -
non-allocating placement allocation functions
void* operator new ( std::size_t count, void* ptr );
(9)
void* operator new[]( std::size_t count, void* ptr );
(10)
As per documentation it state -
Called by the standard single-object placement new expression. The standard library implementation performs no action and returns ptr unmodified.
I am not able to clear myself by what is meant by "non-allocating placement allocation functions"?
These overloads are used by placement new. This is an expression that creates an object at a memory location, but doesn't allocate space for it. For instance, in this toy example:
void foo() {
void *raw = malloc(sizeof(int));
int *pint = new(raw) int(10);
pint->~int();
free(raw);
}
This illustrates that if we need to create an object in memory allocated by something that is not the C++ standard library (in this case, the C allocation functions), special syntax is used to create an object at that location.
The placement operator new accepts the address, and returns it unchanged. Thus the new expression just creates an object there. Naturally, we cannot call delete to free said object and memory, we must do an explicit destructor call, followed by the correct memory deallocation function.
Non-allocating placement allocation function is a form of new that doesn't allocate memory, but rather constructs an object in pre-allocated memory.
See this answer for more details.
To answer the question implied in your title:
It is not permitted to supply your own replacement function for the non-allocating forms of operator new. This is covered in the standard (N4659):
Non-allocating forms [new.delete.placement]
These functions are reserved; a C++ program may not define functions that displace the versions in the C++ standard library.
You can only replace the forms of operator new which are listed as Replacable under the section of the Standard labelled [new.delete].

Allocating object to predefined address in c++ without placement new method

Is it possible in c++ to allocate an object at a specific place in memory? I'm implementing my hobby os kernel memory manager which gives void* addresses to store my stuff and I would like to know how can I use that pointer to allocate my object there. I have tried this:
string* s = (string*)235987532//Whatever address is given.
*s = string("Hello from string\n\0");//My own string class
//This seems to call the strings destructor here even thought I am using methods from s after this in my code...
The only problem with this is that it calls string objects destructor which it shouldn't do. Any help is appreciated.
EDIT: I cannot use placement new because I'm developing in kernel level.
Assignment only works if there's a valid object there already. To create an object at an arbitrary memory location, use placement new:
new (s) string("Hello");
Once you've finished with it, you should destroy it with an explicit destructor call
s->~string();
UPDATE: I just noticed that your question stipulates "without placement new". In that case, the answer is "you can't".
You need to use placement new. There is not an alternative, because this is precisely what placement new is for.
I think you should be able to first implement the operator new used by placement new:
void* operator new (std::size_t size, void* ptr) noexcept
{
return ptr;
}
(See [new.delete.placement] in C++11)
Then, you can use placement new the way it's intended to.
you can use placement new allocation
void* memory = malloc(sizeof(string));
string* myString = new (memory) string();
source: What is an in-place constructor in C++?

Strange C++ new operator usage [duplicate]

This question already has answers here:
What uses are there for "placement new"?
(25 answers)
Closed 9 years ago.
While digging in a C++ project, I encountered a strange usage of C++'s new operator:
int arr[5];
ClassA* a = new(arr) ClassA();
Would you please help me understand this syntax?
It's the placement new syntax - it allows you to construct an object at the pointed-to location in memory. Consider a "normal" use of new:
X *p = new X;
...
delete p;
You can achieve the same effect by doing:
#include <new>
...
void *buffer = ::operator new(sizeof(X));
X *p = new (buffer) X;
...
p->~X();
::operator delete(buffer);
The latter allocates enough memory to hold an X (without constructing an X in it), then explicitly constructs an X in the allocated memory. Later, it explicitly destructs the X it created and then deallocates the memory that contained it.
See also the C++ FAQ: http://www.parashift.com/c++-faq/placement-new.html
This syntax is called the placement new syntax. It is typically used to construct 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 *s1 = new (buf) string("test1"); // placement new
string *s2 = new string("test2"); //ordinary new
When it comes to deallocation, there is no placement delete that automatically does the magic. You should not deallocate every object that is using the memory buffer. Instead you should destruct each object manually, then delete[] only the original buffer
The new() operator can take a size (size in bytes) nothrow_value (returns a null pointer instead of an bad_alloc exception) or pointer(construct the object in the already allocated memory pointed at by this pointer) argument, and in the usage you describe it is creating a new object at the memory location pointed to by arr. For a decent guide on it I would look at this link.
In the case you cited it is using the pointer for arr to create its new instance of ClassA in.

Why are there so many different ways to use new operator in C++

I've just read the new operator explanation on the cplusplus.com. The page gives an example to demonstrate four different ways of using new operator as following:
// operator new example
#include <iostream>
#include <new>
using namespace std;
struct myclass {myclass() {cout <<"myclass constructed\n";}};
int main () {
int * p1 = new int;
// same as:
// int * p1 = (int*) operator new (sizeof(int));
int * p2 = new (nothrow) int;
// same as:
// int * p2 = (int*) operator new (sizeof(int),nothrow);
myclass * p3 = (myclass*) operator new (sizeof(myclass));
// (!) not the same as:
// myclass * p3 = new myclass;
// (constructor not called by function call, even for non-POD types)
new (p3) myclass; // calls constructor
// same as:
// operator new (sizeof(myclass),p3)
return 0;
}
My questions are:
What is the best practice of using
new operator?
Is myclass* p3 = new myclass equivalent to myclass* p3 = new myclass()?
Because they have different purposes. If you didn't want new to throw std::bad_alloc on failure, you would use nothrow. If you wanted to allocate your objects in existing storage, you would use placement new … if you want raw, uninitialized memory, you would invoke operator new directly and cast the result to the target type.
The plain standard usage of new in 99% of all cases is MyClass* c = new MyClass();
To your second question: the new Object() vs. new Object forms are not generally equal. See this question and the responses for the details. But that really is nitpicking. Usually they are equivalent, but to be on the safe side always pick new Object(); Note that, in this particular sample they are equal because MyClass doesn't have any members, so strictly speaking the answer to your question is yes.
1) Several of these are used only in specific, unusual situations. The plain old traditional one is best, most of the time anyway:
X * x = new X();
2) Yes, they are. If the constructor has no arguments, the parentheses are optional. If you're declaring an automatic variable -- i.e.,
X x;
then you must omit the parentheses, or it's a function declaration! As a result, many people will tell you to omit them in the new expression as well. That's a good practice, I think, but I'm just used to including them.
Rather than "best practice", you need them in different situations. For example, most people just want to call new x() to allocate some memory and create the object. However, sometimes you're in situations where you don't want an exception thrown in case new fails, so you call new (nothrow) instead to get a null back.
If you already have some memory allocated but need to create an object, you use "placement new" by calling new (p3) x.
In the rare case where you need to use a class's memory allocator but not actually create an object, you use the (myclass*) operator new (sizeof(myclass)) syntax.
Here are my recommendations:
Prefer not to use new; pass by
reference when possible. (Avoids memory leaks).
Use operator new: x = new X(); // Remember to use delete
Prefer std::vector to array new:
x = new X()[quantity]; // Remember to use delete []
Don't use placement new unless
you absolutely know the reasons.
In general, placement new is used to allocate from specific addresses or a special memory pool. This is an advanced topic.