8.1 C++11对齐支持

一、内存对齐

1.何为内存对齐

对于代码:

        #include <iostream>
        using namespace std;
        struct HowManyBytes{
            char     a;
            int      b;
        };
        int main() {
            cout << "sizeof(char): " << sizeof(char) << endl;
            cout << "sizeof(int): " << sizeof(int) << endl;
            cout << "sizeof(HowManyBytes): " << sizeof(HowManyBytes) << endl;
            cout << endl;
            cout << "offset of char a: " << offsetof(HowManyBytes, a) << endl;	//0
            cout << "offset of int b: " << offsetof(HowManyBytes, b) << endl;	//4
            return 0;
        }
        // 编译选项:g++ -std=c++11 8-1-1.cpp

代码中成员a占1个字节,成员b占4字节,而通过offsetof(用于获取成员变量在类中的偏移量),查看a,b成员位置时,b的位置为4而不是1,这是因为C/C++对数据结构有着对齐要求。

内存对齐是一个整数,意味着该数据成员地址只能位于内存对齐的倍数上,如b位于4而非1。而对齐之间的未使用空间被称为填充数据,如a之后的1,2,3三个字节内容。

对齐方式

2.内存对齐的优势

内存对齐主要有两点优势:

  • 跨平台,有些平台要求内存对齐,否则无法运行
  • 性能,内存对齐有利于提高数据缓存速度。

二、C++11对于内存对齐的支持

1.alignof

C++11支持操作符alignof获取定义完整类型的内存对齐要求,而不支持获取不完整类型或变量对齐值

        #include <iostream>
        using namespace std;
        class InComplete;
        struct Completed{};
        int main(){
            int a;
            long long b;
            auto & c = b;
            char d[1024];
            // 对内置类型和完整类型使用alignof
            cout << alignof(int) << endl          //   4
                << alignof(Completed) << endl;   //   1
                    // 对变量、引用或者数组使用alignof
                    cout << alignof(a) << endl             //   无法编译
                        << alignof(b) << endl              //   无法编译
                        << alignof(c) << endl             //  8,无法编译
                        << alignof(d) << endl;            //  1, 无法编译
                    // 本句无法通过编译,Incomplete类型不完整
                    // cout << alignof(Incomplete) << endl;
                }
                // 编译选项:g++ -std=c++11 8-1-4.cpp

2.alignas

除了获取内存对齐值外,C++11提供对齐描述符alignas()设置内存对齐值,需要注意的是,内存对齐值设置有着一定的要求:

  • 首先,设置值必须是2的幂
  • 其次各平台拥有基准对齐值:std::max_align_t,alignas设置值不允许小于此值(想要设置可以通过#pragma pack(n)或aligns、__declspec(align(#))),
  • 而大于基准对齐值的则称为扩展对齐,扩展对齐也受平台限制,溢出后认为该程序是不规范的。
  • 同一个变量的内存对齐值设置要求一致。
        alignas(double) void f(); // 错误:alignas不能修饰函数
        alignas(double) unsigned char c[sizeof(double)]; // 正确
        extern unsigned char c[sizeof(double)];
        alignas(float)
            extern unsigned char c[sizeof(double)]; // 错误:不同对齐方式的变量定义

下面是一个容量固定但大小随使用数据变化的例子:

        #include <iostream>
        using namespace std;
        struct alignas(alignof(double)*4) ColorVector {
            double r;
            double g;
            double b;
            double a;
        };
        // 固定容量的模板数组
        template <typename T>
        class FixedCapacityArray {
        public:
            void push_back(T t) { /* 在data中加入t变量 */}
            // ...
            // 一些其他成员函数、成员变量等
            // ...
            char alignas(T) data[1024] = {0};
            //int length = 1024 / sizeof(T);
        };
        int main() {
            FixedCapacityArray<char> arrCh;
            cout << "alignof(char): " << alignof(char) << endl;
        cout << "alignof(arrCh.data): " << alignof(arrCh.data) << endl;
        FixedCapacityArray<ColorVector> arrCV;
        cout << "alignof(ColorVector): " << alignof(ColorVector) << endl;
        cout << "alignof(arrCV.data): " << alignof(arrCV.data) << endl;
        return 1;
    }

输出为:

        alignof(char): 1
        alignof(arrCh.data): 1
        alignof(ColorVector): 32
        alignof(arrCV.data): 32

而如果移除17行的alignas(T),则输出为:

        alignof(char): 1
        alignof(arrCh.data): 1
        alignof(ColorVector): 32
        alignof(arrCV.data): 1

很显然,这样在push_back时,将一个对齐值为32的ColorVector塞到对齐值只有1的arrCV.data中,可能会导致一些性能上的丢失(虽然这里我实验了一下也没有什么区别~~~)

3.align

C++11还提供函数:

        void* align( std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space );

用于设置指定地址ptr后指定大小space的内存对齐值。

4.aligned_storage和aligned_union

        template< std::size_t Len, std::size_t Align = /*default-alignment*/ >
        struct aligned_storage;
        template< std::size_t Len, class... Types >
        struct aligned_union;

感觉C++11这两个属性还不成熟,后面的标准进一步完善了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值