Если я выделяю память для некоторого типа T - пусть это в шаблоне, скажем -
template
то места гарантированно хватит для n элементов с типом T или нет? Какие-то проблемы из-за выравнивания могут быть? И если могут - то как их правильно решить?
Дополнение - по совету @VladD я ппробовал выделить память с особыми требованиями к выравниванию:
#include
using namespace std;
struct alignas(256) D {
char a;
char b;
};
template
template
int main() {
cout << allocSize
GCC это не смог отработать - https://ideone.com/dgo75h. Но Visual Studio нормально отработал, но выдал:
sizeof = 256, alignof = 256
type = union std::_Align_type
т.е. понял и размер, и выравнивание, но адрес дал выровненный явно не на 256. Мне это выравнивание не нужно, это так, игры - но тем не менее получается, что так выделять память не получается?
Ответ
По идее, вам нужно std::aligned_storage
Должно по идее работать так:
template
Проблемы из-за выравнивания с простым подходом очевидны: new char[] не знает ваших требований по выравниванию, и может выделить неправильно выровненную память.
Для выделения объектов в вашей памяти вам понадобится placement new. Вам должен пригодится std::align, использование которого описано здесь
Обновление: я перепроверил, и на самом деле new не соблюдает кастомные требования по выравниванию. Поэтому нужно делать выравнивание самостоятельно, при помощи std::align. Получается вот что:
// подсчёт длины нужной аллокации
template
Применяем:
struct alignas(1024) S
{
};
// выделёем память на 3 экземпляра
size_t total_space = aligned_char_size(3);
void* p = new char[total_space];
std::cout << p << std::endl;
// получаем выровненный указатель при помощи std::align
void* allocated_item = p;
size_t remaining_space = aligned_char_size(3);
if (std::align(alignof(S), sizeof(S), allocated_item, remaining_space))
{
std::cout << allocated_item << std::endl;
std::cout << (size_t)allocated_item % alignof(S) << std::endl;
}
else
{
std::cout << "Impossible" << std::endl;
}
Результат на Visual Studio 2017:
000002333DF15950
000002333DF15C00
0
Если убрать alignas(1024), получаем
000002A27FD2ECD0
000002A27FD2ECD0
0
Комментариев нет:
Отправить комментарий