C++11 新特性alignof alignas std::aligned_storage std::align

在现代计算机系统中,CPU通过总线读取设备的数据一般是8B对齐读的,如果一个对象的指针不按照8B对齐,那么肯定效率不高,另外CPU Cache的CacheLine也是64B或者128B,所以内存对齐在高性能C++编程中是一个很重要的问题。

C++11引入了几个新概念,alignof alignas std::aligned_storage std::align,其中alignof 和alignas是关键词,std::aligned_storage是类,std::align是函数。

alignment

在C++程序里的对象,结构体在编译的时候都会按照alignment来内存对齐,一般基础类型会按照sizeof的大小来对齐,对齐的大小也就是alignment。

比如一个变量int a,取a的地址ptr,ptr的地址一定满足ptr % 4 == 0

可以在编译期检查内存对齐的宏:

#define CHECK_ALIGN(ptr, alignment)                       \
  do{                                                     \
    constexpr size_t status                               \
       = reinterpret_cast<uintptr_t>(ptr) % alignment;    \
    static_assert(status == 0, "ptr must be aligned");    \
  }while(0)                                               \

alignof

alignof是C++11引入的关键词,可以得到类型的内存对齐要求,用法类似于sizeof

#include <iostream>

int main()
{
    char a;
    int b;
    long c;

    std::cout << "alignof(char) " << alignof(a) << " alignof(int) "
            << alignof(b) << " alignof(long) " << alignof(c) << std::endl;

    return 0;
}

g++ x.cpp -std=c++11

alignof(char) 1 alignof(int) 4 alignof(long) 8

对于复杂类型来说,情况又有些不同,可以看到alignof返回的是最大的属性的alignment,而sizeof保证了所有字段在内存对齐时的长度,下面的例子把两个char的字段放到了4个字节里,为了和下面的int对齐。

有时候我们在存储领域工作时,需要把内存的结构和磁盘上的数据完全一样,而内存对齐会浪费磁盘空间,这时候我们可以使用#pragma pack(1)来避免自动对齐

alignas

alignas是C++引入的新关键词,作用是改变一个类的alignment,比如从CacheLine或者SIMD操作等角度考虑,更改类的alignment会更有效率,在C++11之前可以用gcc提供的__attribute__(__aligned__(alignment))来实现。

另外用alignas来修改alignment时有一些限制,首先不能小于原生的对齐需求,其次alignment必须是2的整数次幂。

std::aligned_storage

std::aligned_storage是C++11中新引入的一个用于满足内存对齐要求的静态内存分配类,位于type_traits

当类std::aligned_storage的对象构造完成时,就分配了长度为len,而且内存地址满足algin的对齐要求。

std::align

std::align是C++11中引入的一个方法,可以用来从一段内存中出去满足alignment对齐需求的内存。

最后更新于