4

Consider the following object:

std::array<std::aligned_storage_t<sizeof(T), alignof(T)>, size> container;

If I have already called placement new on the first element of this array, I believe it is perfectly acceptable to do the following:

reinterpret_cast<T *>(container.data());

This is because data() returns a pointer to the underlying array, which can also be treated as a pointer to the first element of that underlying array. I have allocated, via placement new, an object at that location, so at that location there is an object of type T.

Note that reinterpret_cast should be valid here rather than a static_cast chain, see static_cast and reinterpret_cast for std::aligned_storage.

However, what if I have not actually called placement new? Is it legal for me to construct this pointer, as long as I do not dereference it?

My motivation here is implementing a std::vector-like class backed by an static array (so no indirection or dynamic allocation). I am trying to implement the data() member function. It is convenient to be able to have an always-valid, zero-overhead way of creating a pointers + size pair that represent the data: data(), size(). Since size() would return 0, I end up constructing a pointer that I never dereference.

David Stone
  • 26,872
  • 14
  • 68
  • 84
  • 1
    Yes, the `reinterpret_cast`, by itself, is safe. – T.C. Sep 05 '15 at 18:55
  • 1
    Why not use a custom allocator with the already existing `std::vector` and have the allocator allocate on the stack using a size template parameter? But anyway, just doing a cast is safe. – Brandon Sep 05 '15 at 19:05
  • @Brandon: That wastes the space of at least `sizeof(void *) * 2` for the pointers within the vector. It also causes all of my accesses to go through pointers, and indirect access can kill pipelining, depending on how easily the compiler / processor can see through that, and that is the sort of thing that optimizers are not always good at doing. I almost exclusively do work where space overhead equals time overhead. – David Stone Sep 05 '15 at 19:26
  • 2
    `However, what if I have not actually called placement new? Is it legal for me to construct this pointer, as long as I do not dereference it?` "**[basic.life]/5** Before the lifetime of an object has started but after the storage which the object will occupy has been allocated ... any pointer that refers to the storage location where the object will be ... located may be used but only in limited ways..." The paragraph goes on to detail those ways. You'd be fine as long as you stay within these limits. – Igor Tandetnik Sep 05 '15 at 20:52
  • 1
    @IgorTandetnik: Make that an answer and I will accept it – David Stone Sep 06 '15 at 15:46

0 Answers0