zoukankan      html  css  js  c++  java
  • C++11:25内存对齐

    25、内存对齐

    0、课前秀

    1、内存对齐介绍

    • 内存对齐(字节对齐):是一个数据类型所能存放的内存地址的属性。当我们说一个数据类型的内存对齐为8时,就是指这个数据类型所定义出来的所有变量的内存地址都是8的倍数。
    • 当一个基本数据类型(Fundamental Types)的对齐属性和这个数据类型的大小相等时,这种对齐方式称为自然对齐(Naturally Aligned)
    • 对于结构体而言,默认的对齐将等于其中最大的成员的对齐值。

    2、堆内存的内存对齐

    • 实际上,malloc一般使用当前平台默认的最大内存对齐数对齐内存。
    • 当我们需要分配一块具有特定内存对齐的内存块时,在MSVC下应当使用_aligned_malloc,而在gcc下一般使用memalign等函数。
    • aligned_malloc的实现.cpp
    #include<assert.h>
    inline void* aligned_malloc(size_t size, size_t alignment)
    {
        //检查alignment是否是2的N次方
        assert(!(alignment & (alignment - 1)));
        //计算出一个最大的offset,sizeof(void*)是为了存储原始指针地址
        size_t offset = sizeof(void*) + (--alignment);
        
        //分配一块带offset的内存
        char* p = static_cast<char*>(malloc(offset + size));
        if(!p) return nullptr;
        
        //通过"&(~alignment)"把多计算的offset减掉
        void* r = reinterpret_cast<void*>(reinterpret_cast<size_t>(p + offset) & (~alignment));
        
        //将r当作一个指向void*的指针,在r当前地址前面放入原始地址
        static_cast<void**>(r)[-1] = p;
        //返回经过对齐的内存地址
        return r;
    }
    
    inline void aligned_free(void* p)
    {
        //还原加原始地址,并free
        free(static_cast<void**>(p)[-1]);
    }
    

    3、利用alignas指定内存对齐大小

    • 使用代码
    alignas(32) long long a = 0;
    
    #define XX 1
    struct alignas(XX) MyStruct_1 {}; //OK
    
    template <size_t YY = 1>
    struct alignas(YY) MyStruct_2 {}; //OK
    
    static const unsigned ZZ = 1;
    struct alignas(ZZ) MyStruct_3 {}; //OK
    
    • alignas只能改大不能改小,改小仍然需要使用#pragma pack

    4、利用alignof和std::alignment_of获取内存对齐大小

    • alignof用来获取内存对齐大小,用法如下:
    MyStruct xx;
    std::cout << alignof(xx) << std::endl;
    std::cout << alignof(MyStruct) << std::endl;
    
    • std::alignment_of的功能是编译期计算类型的大内存对齐。例子
    struct MyStruct
    {
        char a;
        int b;
        double c;
    };
    
    int main()
    {
        int alignsize = std::alignment_of<MyStruct>::value;//8
        int sz = alignof(MyStruct);//8
        
        return 0;
    }
    

    5、内存对齐的类型std::aligned_storage

    • std::aligned_storage可以看成一个内存对齐的缓冲区,它的原型如下:template<std::size_t Len, std::size_t Align = /*default-alignment*/> struct aligned_storage;
    • std::aligned_storage一般和placement new结合使用,它的基本用法如下:
    #include <iostream>
    #include <type_traits>
    
    struct A
    {
        int avg;
        A(int a, int b):avg((a+b)/2){}
    };
    
    typedef std::aligned_storage<sizeof(A),alignof(A)>::type Aligned_A;
    
    int main()
    {
        Aligned_A a,b;
        new (&a) A(10,20);
        b = a;
        std::cout << reinterpret_cast<A&>(b).avg << std::endl;
        return 0;
    }
    

    6、std::max_align_t和std::align操作符

    • std::max_align_t用来返回当前平台的最大默认内存对齐类型。
    • 用如下方式获得当前平台的最大默认内存对齐数:std::cout << alignof(std::max_align_t) << std::endl;
    • std::align用来在一大块内存当中获取一个符合指定内存要求的地址,例子如下:
    char buffer[] = "-------------";
    void* pt = buffer;
    std::size_t space = sizeof(buffer) - 1;
    std::align(alignof(int), sizeof(char), pt, space);
    

    ReadMe

    • 20200514开了个头,20200526白天看完,整理一波,也没感觉到使用场景在哪,先把知识点记下再说吧。
  • 相关阅读:
    python cook 整理
    Ajax
    跨站请求伪造 CSRF
    tornado web
    python hashable
    扩大了一个逻辑卷,resize2fs 保错:没有这个超级块
    linux重启后进入了救援模式,无法远程登录
    如何安装JDK以及配置win10的环境变量
    输出菱形
    6.28作业(2.使用3种方式求100以内偶数和)
  • 原文地址:https://www.cnblogs.com/fewolflion/p/12968637.html
Copyright © 2011-2022 走看看