1
#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?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
user3702643
  • 1,465
  • 5
  • 21
  • 48
  • 4
    Because you told C++ to create the objects at address `MainBlock`. – tkausl Jan 27 '19 at 10:51
  • @tkausl That makes sense. So I am actually creating only one object? – user3702643 Jan 27 '19 at 10:53
  • 1
    Technically, you're creating multiple objects. They just happen to live at the same address (which is undefined behavior if I remember correctly). – tkausl Jan 27 '19 at 10:55
  • @tkausl It seems to be well-defined; the array created by the first placement-new call is destroyed due to "reusing its' storage" by the second placement-new call. [`[basic.life]/1.4`](http://eel.is/c++draft/basic.life#1.4) – HolyBlackCat Jan 27 '19 at 10:56
  • @user3702643 In addition to answers below, note that you should probably never use placement-new to create arrays. See [Can placement new for arrays be used in a portable way?](https://stackoverflow.com/questions/15254/can-placement-new-for-arrays-be-used-in-a-portable-way) – HolyBlackCat Jan 27 '19 at 10:58

3 Answers3

2

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.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • Good point about `delete []`. For this reason, it probably makes sense to declare MainBlock as `char * const` so as not to accidentally reassign it. – dsp_user Jan 27 '19 at 11:42
1

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.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
0

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.

Community
  • 1
  • 1
frogatto
  • 28,539
  • 11
  • 83
  • 129