I'm having trouble understanding what the difference is between using span<T>
to create a view over some memory area/buffer as a struct of type T
, or using placement-new
to initialize a pointer type.
Functionally, they both allow you to write something like foos[0]
, and to read/write to the underlying memory area.
If I understand it correctly, the placement-new starts the "lifetime" of the pointers in the memory area/buffer -- but functionally, I don't notice any difference in effects between the two.
Below shows an example of what I mean:
// BUFFER
// |==================================|
// | Page | Page | Page | Page | Page |
// |==================================|
// ^ ^
// 0 bytes (4096 * 5) bytes
#include <cstddef>
#include <cstdio>
#include <span>
#include <cassert>
struct alignas(4096) Page { int id; };
alignas(4096) std::byte buffer[4096 * 5];
// Using placement-new to initialize Page pointers in the buffer
Page* page_ptrs = new (buffer) Page;
// Using span<T> to create a view of Pages over the buffer
auto pages = std::span<Page>(reinterpret_cast<Page*>(buffer), 5);
int main()
{
// Get first and second page using page_ptrs
Page* first_page = &page_ptrs[0];
Page* second_page = &page_ptrs[1];
first_page->id = 1;
second_page->id = 2;
// Get first and second page using pages
Page first_page_2 = pages[0];
Page second_page_2 = pages[1];
printf("first_page.id = %d, second_page.id = %d \n", first_page->id, second_page->id);
printf("first_page_2.id = %d, second_page_2.id = %d \n", first_page_2.id, second_page_2.id);
assert(first_page->id == first_page_2.id);
assert(second_page->id == second_page_2.id);
// Update the page ID's using the span<T>
pages[0].id = 3;
pages[1].id = 4;
assert(first_page->id == 3);
assert(second_page->id == 4);
}