C++17及以上:std::allocator是否支持过对齐类型?需手动处理吗?
关于C++17及以上分配器对齐的问题解答
问题1:若C++17及以上标准保证分配器必须支持过对齐类型,是否意味着我们可以避免创建手动对齐类型?
是的,完全可以。C++17标准对分配器模型做了关键更新:所有符合标准的分配器(包括std::allocator)必须支持过对齐类型(即对齐要求大于alignof(std::max_align_t)的类型)。
具体来说,标准要求分配器的allocate成员函数(以及通过std::allocator_traits调用的分配接口)能够接受std::align_val_t类型的参数,以此返回满足指定对齐要求的内存块。只要你在分配内存时正确传递目标类型的对齐要求(比如通过alignof(T)构造align_val_t),分配器就会返回符合要求的内存,不需要手动创建额外的过对齐包装类型来“凑”对齐。
问题2:当自定义vector使用std::allocator进行内存分配时,在C++17及以上环境下,是否仍需创建带alignas的内部过对齐类型OT,分配OT后将OT通过reinterpret_cast转换为T,再在迭代器的operator中解引用指针,以此支持类型的过对齐?还是std::allocator会自动正确对齐,直接解引用T就能返回正确对齐的元素引用?
不需要再用这种手动包装的老办法了,std::allocator在C++17及以上会自动处理过对齐需求,直接使用T*解引用即可。
正确的实现方式是:
- 当自定义vector需要为类型
T分配内存时,先确定T的对齐要求:如果alignof(T) > alignof(std::max_align_t),则需要在调用分配器的allocate时,传递std::align_val_t{alignof(T)}作为额外参数;如果是默认对齐,则不需要额外参数。 - 可以直接通过
std::allocator_traits<std::allocator<T>>::allocate(alloc, n, std::align_val_t{alignof(T)})来统一处理两种情况(allocator_traits会自动判断是否需要传递对齐参数)。 - 分配得到的内存指针可以直接转换为
T*(前提是按T的对齐要求分配了内存),直接解引用这个T*就能得到正确对齐的T对象引用,完全不需要中间的OT类型和reinterpret_cast操作。
这种手动包装的方式是C17之前的妥协方案——因为当时的分配器模型不支持过对齐,只能通过创建一个对齐要求更高的辅助类型来间接获取对齐内存。C17之后标准已经解决了这个问题,完全可以抛弃这种繁琐且容易出错的写法。
内容的提问来源于stack exchange,提问作者metamorphosis
相关产品推荐
相关产品推荐

