Reputation: 503
I was trying to implement my own small allocator for testing purposes, and while designing it I thought that I don't know how to implement it without violating strict aliasing rule.
In most open-source from GitHub, C++ allocator method allocate<T>
is an adapter to memory: it runs to the memory, asks for N
consecutive std::byte
s or unsigned char
s, and then reinterpret_cast
's this memory to T
, and after that gives the memory back to its callee.
However, how does that not break the strict aliasing rule (even though the callee must call constructors itself, we cast std::byte*
to T*
). How is it possible to work-around it when implementing a simple buffer allocator that's suitable for most STL containers?
Upvotes: 2
Views: 215
Reputation: 96791
Strict aliasing is violated when you pretend that there's an object at a certain memory location, but in reality there isn't. (You do that by reinterpret_cast
ing a pointer/reference and then dereferencing it, where only the deferencing itself is UB.)
It doesn't stop you from using placement-new to change what type of object is stored in some memory, and then accessing it.
For example:
#include <string>
int main()
{
alignas(std::string) char buf[sizeof(std::string)];
*reinterpret_cast<std::string*>(buf) = "foo"; // UB
std::string *ptr = new(buf) std::string;
*ptr = "foo"; // Legal.
}
Upvotes: 3
Reputation: 63142
std::allocator<T>::allocate
does not construct any objects of type T
1, std::construct_at
does. It's ok to reinterpret_cast
a void *
to a T *
, if you then go on to start the lifetime of a T
in the memory pointed to.
allocate
does start the lifetime of an array of T
, but not the T
subobjects of that array.Upvotes: 4