The result of a placement new always seems to be the same as the memory pointer that I provide to the placement new. With GCC this seems to hold true even for classes with virtual functions, for example...
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
int a;
virtual ~A() {}
};
int main()
{
void *mem = malloc(sizeof(A));
A* ptr = new(mem) A();
cout << "sizeof(T) = " << sizeof(A) << endl;
cout << "mem = " << mem << endl;
cout << "ptr = " << ptr << endl;
cout << "addr a = " << &(ptr->a) << endl;
ptr->~A();
free(mem);
return 0;
}
The output of this program is (note: 64 bit linux)...
sizeof(T) = 16
mem = 0x1a41010
ptr = 0x1a41010
addr a = 0x1a41018
Does C++ guarantee that mem and ptr are identical or is this just a GCC coincidence? In a larger portable program, will I have to preserve both mem and ptr or can I just preserve one of them and cast when needed?
To clarify the question a bit, I know that memory allocators will sometimes put the size of an allocated block in the word before the pointed to block of memory. Are C++ compilers allowed to use tricks like that and say put the VMT pointer in the word before the block of memory to which an object pointer points? In this case mem and ptr would be different.
Yes, they're the same. You might like to think of a memory address as a void pointer and of an object address as a typed pointer, but if you like, you can cast. In some sense, new
is the way to "convert" a memory address into an object (by constructing one). Here's the full picture (note how there are no casts):
void * addr = std::malloc(sizeof(T)); // or ::operator new(sizeof(T))
T * p = ::new (addr) T; // "new" gives you an object pointer
p->~T();
std::free(addr);
This is only true for the non-array version of new
, though. Array-placement-new is different, and essentially unusable.
You might like to look at your implementation of std::allocator
to see placement-new and casting in action.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With