C++ 为多个缓冲区分配内存,包括对齐

C++ 为多个缓冲区分配内存,包括对齐,c++,alignment,C++,Alignment,我想为几种不同类型的连续数组分配内存。也就是说,与此类似,但具有动态大小: template <typename T0, std::size_t N0, typename T1, std::size_t N1, ...> struct { T0 t0s[N0]; T1 t1s[N1]; ... }; 例如: auto offsets = calculateOffets<char, float>({3, 2}); // Offsets is now

我想为几种不同类型的连续数组分配内存。也就是说,与此类似,但具有动态大小:

template <typename T0, std::size_t N0, typename T1, std::size_t N1, ...>
struct {
    T0 t0s[N0];
    T1 t1s[N1];
    ...
};
例如:

auto offsets = calculateOffets<char, float>({3, 2});
// Offsets is now {4, 12} because the layout is [cccXffffFFFF] where c is a char, X is padding, f and F are the two floats.
// Now we can allocate a buffer of size offsets.back() with alignment alignof(char) and placement-new 3 chars starting at buf + 0, and 2 floats at buf + offsets.front()
auto offset=calculateOffets({3,2});
//偏移量现在是{4,12},因为布局是[CCCXFFFFFF],其中c是字符,X是填充,f和f是两个浮点。
//现在我们可以分配一个大小为offsets.back()的缓冲区,对齐方式为alignof(char),放置新的3个char,从buf+0开始,在buf+offsets.front()处放置2个float
这很有趣,因为编译器显然内置了这种逻辑,因为在编译时,当大小是静态的时,它知道上面结构的布局

(到目前为止,我只对POD类型感兴趣;要完全通用,我还需要处理异常安全构造和破坏。)

是否有一些现成的方法来计算这样的动态结构的大小和偏移

标准库中没有这样的函数。您可能可以在循环中使用
std::align
实现它

是否有一些现成的方法来计算这样的动态结构的大小和偏移


标准库中没有这样的函数。可以使用<代码> STD::在循环中对齐Alg/<代码> .< /P> < P>没有内置的工具,但是这是C++中的可解决的问题。 由于您实际上在寻找的是对齐的连续组件的“打包缓冲区”,因此我建议您通过在最对齐的对象的对齐处分配所有缓冲区的总和来实现这一点。这使得以字节为单位的缓冲区长度的计算变得容易——但需要重新映射数据的顺序

对齐时要记住的是,16字节边界也与8字节边界对齐(以此类推)。另一方面,来自1字节边界的4字节不在4字节边界上,这是不正确的。可能是,但这取决于初始指针

例子 例如,我们希望缓冲区中包含以下内容:

  • 3
    char
    s(
    c
  • 2
    float
    s(
    f
  • 2
    short
    s(
    s
我们假设以下是正确的:

  • alignof(float)>=alignof(short)>=alignof(char)
  • sizeof(float)
    is
    4
  • sizeof(short)
    is
    2
  • sizeof(char)
    is
    1
根据我们的需要,我们需要一个
sizeof(float)*2+sizeof(short)*2+sizeof(char)*3
=
15
字节的缓冲区

按路线排序的缓冲区在打包时的外观如下所示:

ffff ffff ssss ccc
只要初始分配与
alignof(float)
对齐,该缓冲区中的其余字节也保证适当对齐

如果您可以将数据安排为始终按降序排列,这将是理想的;但是,如果不能保证这种情况,您可以始终使用预先封装好的模板元编程解决方案,根据每个对象的
alignof(T)
T..
类型列表进行排序


1您建议按缓冲区顺序对齐的问题是,像
alignof(char)
这样的情况,即
1
字节,不能保证
3
char
s之后和
1
初始对齐的填充字节与
4
字节对齐。
0x00FFFFFE01
的指针为“1字节对齐”,但4字节之后为
0x00FFFFFE05
——仍然未对齐


尽管这可能适用于某些底层分配器,如
new
/
std::malloc
,其默认对齐方式为
alignof(std::max\u align\t)< /代码>——对于更精确的分配机制,如在 STD::PrimulICIAL ApLoosiver < /C> > 

< P> >中,没有这种内置的设施,但这是C++中的可解问题。 由于您实际上在寻找的是对齐的连续组件的“打包缓冲区”,因此我建议您通过在最对齐的对象的对齐处分配所有缓冲区的总和来实现这一点。这使得以字节为单位的缓冲区长度的计算变得容易——但需要重新映射数据的顺序

对齐时要记住的是,16字节边界也与8字节边界对齐(以此类推)。另一方面,来自1字节边界的4字节不在4字节边界上,这是不正确的。可能是,但这取决于初始指针

例子 例如,我们希望缓冲区中包含以下内容:

  • 3
    char
    s(
    c
  • 2
    float
    s(
    f
  • 2
    short
    s(
    s
我们假设以下是正确的:

  • alignof(float)>=alignof(short)>=alignof(char)
  • sizeof(float)
    is
    4
  • sizeof(short)
    is
    2
  • sizeof(char)
    is
    1
根据我们的需要,我们需要一个
sizeof(float)*2+sizeof(short)*2+sizeof(char)*3
=
15
字节的缓冲区

按路线排序的缓冲区在打包时的外观如下所示:

ffff ffff ssss ccc
只要初始分配与
alignof(float)
对齐,该缓冲区中的其余字节也保证适当对齐

如果您可以将数据安排为始终按降序排列,这将是理想的;但是,如果不能保证是这种情况,您可以始终使用预先封装的模板元编程解决方案对
T..列表进行排序。
auto offsets = calculateOffets<char, float>({3, 2});
// Offsets is now {4, 12} because the layout is [cccXffffFFFF] where c is a char, X is padding, f and F are the two floats.
// Now we can allocate a buffer of size offsets.back() with alignment alignof(char) and placement-new 3 chars starting at buf + 0, and 2 floats at buf + offsets.front()