25、内存对齐0、课前秀1、内存对齐介绍内存对齐(字节对齐):是一个数据类型所能存放的内存地址的属性。当我们说一个数据类型的内存对齐为8时,就是指这个数据类型所定义出来的所有变量的内存地址都是8的倍数。当...
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白天看完,整理一波,也没感觉到使用场景在哪,先把知识点记下再说吧。
沃梦达教程
本文标题为:C++11:25内存对齐
基础教程推荐
猜你喜欢
- 详解c# Emit技术 2023-03-25
- C语言基础全局变量与局部变量教程详解 2022-12-31
- C++详细实现完整图书管理功能 2023-04-04
- C语言 structural body结构体详解用法 2022-12-06
- C++中的atoi 函数简介 2023-01-05
- 一文带你了解C++中的字符替换方法 2023-07-20
- 如何C++使用模板特化功能 2023-03-05
- C/C++编程中const的使用详解 2023-03-26
- C利用语言实现数据结构之队列 2022-11-22
- C++使用easyX库实现三星环绕效果流程详解 2023-06-26