Do new (pointerT) T()
in a loop. Please keep pointerT
inside an object whose destructor destroys the objects and calls free
(call it eg. aligned_vector
), and in the constructor, do:
ptrdiff_t k = 0;
try
{
for (; k < n; k++)
new (pointerT + k) T();
}
catch (...)
{
for (; k > 0; k--) (pointerT + k)->~T();
free(pointerT);
throw;
}
This way, if a construction fails, you can bail out transactionally and not leak memory or resources.
For this purpose, the simplest in terms of reusability would be to implement your own alignment aware allocator and use std::vector
, which takes care of exception safety (and many other goodies) for you.
Here is a sample allocator, C++11, with compile time alignment specification (please suggest enhancements and corrections):
template <typename T, size_t align>
struct aligned_allocator
{
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
template <typename U>
struct rebind { typedef aligned_allocator<U, align> other; };
T* address(T& t) { return &t; }
T* allocate(size_t n, const T* = 0)
{
if (T* ans = memalign(align, n * sizeof(T))) return ans;
else throw std::bad_alloc();
}
T* deallocate(T* p, size_t) { free(p); }
size_t max_size() const
{
return size_t(-align) / sizeof(T);
}
template <typename U, typename... Args>
void construct(U* p, Args&&... args)
{
::new((void *)p U(std::forward<Args>(args)...);
}
template <typename U>
void destroy(U* p) { p->~U(); }
};
Sample usage: std::vector<T, aligned_allocator<T, 64>> v(42);
constructs a vector with aligned storage and 64 elements.
You can also do, in C++11
template <typename T, size_t align>
using aligned_vector = std::vector<T, aligned_allocator<T, align>>;
and you can now use
aligned_vector<MyType, 64> v;
and enjoy an exception safe, move aware, iterators aware, range-based-for-loop aware, etc, vector with aligned storage.