Moje pytanie jest raczej proste;Czy specyfikator alignas działa z "nowym"?
Czy specyfikator alignas działa z "nowym"? Oznacza to, że jeśli struktura jest zdefiniowana do wyrównania, czy zostanie wyrównana przy przydzielaniu do nowej?
Moje pytanie jest raczej proste;Czy specyfikator alignas działa z "nowym"?
Czy specyfikator alignas działa z "nowym"? Oznacza to, że jeśli struktura jest zdefiniowana do wyrównania, czy zostanie wyrównana przy przydzielaniu do nowej?
Jeśli wyrównanie typu nie jest zbyt wyrównane, to tak, domyślny new
zadziała. "Wyrównanie wyrównane" oznacza, że wyrównanie określone w alignas
jest większe niż alignof(std::max_align_t)
. Domyślnie new
będzie działać z typami nieprostokątnymi mniej lub bardziej przypadkowo; domyślny alokator pamięci zawsze przydzieli pamięć z wyrównaniem równym alignof(std::max_align_t)
.
Jeśli jednak wyrównanie Twojego typu jest zbyt wyrównane, nie masz szczęścia. Ani domyślny new
, ani żaden globalny operator new
, który napiszesz, nie będą w stanie poznać wymaganego wyrównania typu, nie mówiąc już o przydzieleniu odpowiedniej dla niego pamięci. Jedynym sposobem, aby pomóc w tym przypadku, jest przeciążenie klasy operator new
, która będzie w stanie zapytać o wyrównanie klasy z alignof
.
Oczywiście nie będzie to przydatne, jeśli ta klasa jest używana jako członek innej klasy. Nie, chyba że ta druga klasa również przeciąży operator new
. Coś tak prostego, jak new pair<over_aligned, int>()
nie będzie działać.
Propozycja dla C++ 17 (która została zaakceptowana) dodaje support for dynamic allocation of over-aligned types, poprzez przeciążenia operator new/delete
, które pobierają alignof
typu, który jest przydzielany. Spowoduje to również wyrównanie wierszy mniejszych niż typ wyrównany do maksimum, więc przydział pamięci nie musi zawsze zwracać pamięci wyrównanej do alignof(std::max_align_t)
.
Mimo to kompilatory nie są wymagane w przypadku , aby w ogóle obsługiwać typy wyrównane.
Nie, nie ma. Struktura zostanie dopełniona do żądanego wyrównania, ale nie zostanie wyrównana. Istnieje jednak szansa, że będzie to allowed in C++17 (fakt, że ta propozycja C++ 17 powinna być całkiem dobrym dowodem, że to nie działa w C++ 11).
Widziałem, jak to działa z niektórymi alokatorami pamięci, ale to było szczęście. Na przykład, niektóre alokatory pamięci dopasują swoje przydziały pamięci do mocy 2 żądanego rozmiaru (do 4KB) jako optymalizację alokatora (zmniejszają fragmentację pamięci, prawdopodobnie ułatwiają ponowne wykorzystanie pamięci zwolnionej wcześniej, itp.) . Jednak nowe implementacje/malloc, które są zawarte w OS X 10.7 i CentOS 6 systemów, które testowałem nie rób tego i nie z następującego kodu:
#include <stdlib.h>
#include <assert.h>
struct alignas(8) test_struct_8 { char data; };
struct alignas(16) test_struct_16 { char data; };
struct alignas(32) test_struct_32 { char data; };
struct alignas(64) test_struct_64 { char data; };
struct alignas(128) test_struct_128 { char data; };
struct alignas(256) test_struct_256 { char data; };
struct alignas(512) test_struct_512 { char data; };
int main() {
test_struct_8 *heap_8 = new test_struct_8;
test_struct_16 *heap_16 = new test_struct_16;
test_struct_32 *heap_32 = new test_struct_32;
test_struct_64 *heap_64 = new test_struct_64;
test_struct_128 *heap_128 = new test_struct_128;
test_struct_256 *heap_256 = new test_struct_256;
test_struct_512 *heap_512 = new test_struct_512;
#define IS_ALIGNED(addr,size) ((((size_t)(addr)) % (size)) == 0)
assert(IS_ALIGNED(heap_8, 8));
assert(IS_ALIGNED(heap_16, 16));
assert(IS_ALIGNED(heap_32, 32));
assert(IS_ALIGNED(heap_64, 64));
assert(IS_ALIGNED(heap_128, 128));
assert(IS_ALIGNED(heap_256, 256));
assert(IS_ALIGNED(heap_512, 512));
delete heap_8;
delete heap_16;
delete heap_32;
delete heap_64;
delete heap_128;
delete heap_256;
delete heap_512;
return 0;
}
To prawda, najlepsza odpowiedź nie jest. C++ 11 * * da ci prawidłowe wyrównanie dla obiektów przydzielonych do stosu, ale domyślne alokatory pamięci nie dadzą prawidłowego wyrównania. Na razie musisz używać funkcji POSIX/windows owiniętych w makra wykrywające system operacyjny. Na przykład; posix_memalign w systemach Linux/OSX/BSD i aligned_alloc w systemie Windows. Dla osób używających Intel MKL dostępne są mkl_malloc i mkl_free. – alfalfasprout
dodać: Można zapytać to maksymalne dopasowanie poprzez ' alignof (std :: max_align_t) '. Typy z wyrównaniem większym niż to nazywa się * over-wyrównane *, a ich obsługa jest warunkowa, definiowana przez implementację. – GManNickG
Okazuje się, że tak naprawdę tego nie potrzebuję, mimo to dobrze jest wiedzieć! – Skeen
Czy można zrobić coś, aby podnieść limit, aby uzyskać maksymalne wyrównanie w g ++? – Skeen