Reputation: 1588
When browsing operator new, operator new[] - cppreference.com, it seems we have a number of options for allocating arrays of objects with specific alignment requirements. However, it is not specified how to use them, and I can't seem to find the correct C++ syntax.
Can I somehow make an explicit call to this operator, or will the compiler automatically infer the overload? :
void* operator new[]( std::size_t count, std::align_val_t al );
Looking at Bartek's coding blog, it seems like the compiler will automatically choose an overload based on whether or not the alignment requirement is larger than __STDCPP_DEFAULT_NEW_ALIGNMENT__
(which is usually 16 on 64-bit machines).
Is it possible to manually choose an overload for the new
operator in some cases? Sometimes I might want an allocated block to be aligned in a certain way (I assume the alignment to always be a power of 2, and likely larger than 16).
I'm probably going to be using GCC and C++ >= 17 for the foreseeable future.
Upvotes: 12
Views: 16331
Reputation: 248
Looks like I'm a bit late :)
But since I also stumbled on this topic with the very same question, felt like it makes sense to bring some clarity
So the thing is, it seems that the compiler is smart enough to reach for a said overload of new
only when it sees a type with special
alignment requirements, i.e. more aligned than STDCPP_DEFAULT_NEW_ALIGNMENT
(points 3,4 on cppreference)
- Called by new to allocate storage required for a single object whose alignment requirement exceeds STDCPP_DEFAULT_NEW_ALIGNMENT.
- Called by new[] to allocate all storage required for an array of objects whose alignment requirement exceeds STDCPP_DEFAULT_NEW_ALIGNMENT.
Here (and here as well) is a snippet that shows that it indeed happens:
#include <iostream>
void* operator new ( std::size_t count, std::align_val_t al ) {
std::cerr << "aligned alloc call with alignment=" << (std::size_t)al << " and count=" << count << std::endl;
return ::operator new (count); ///< definitely not a good idea, but ok for this purpose
}
struct alignas(32) Overaligned {};
int main() {
Overaligned* op = new Overaligned{};
std::cerr << (const void*)op; // here just so that the compiler doesn't optimize away everything :)
}
So yes, it will call it :) But if you so wish, you can allocate the memory by hand and then place stuff there:
::operator new[](sizeof(YourType), align_val_t{alignof(YourType)})
Upvotes: 1
Reputation: 4725
Additional arguments to operator new
are passed within parentheses before the type:
#include <new>
int* allocate() {
return new (std::align_val_t(16)) int[40]; // 128-bit alignment
// will call `void* operator new[](size_t, align_val_t)`
}
Upvotes: 22