C++11/14新特性--内存对齐


1、现象

先看一段代码:

struct s1
{
    char s;
    int i;
};
 
struct s2
{
    int i;
    double d;
};
 
cout << "-------basic type" << endl;
cout << "sizeof(char) " << sizeof(char) << endl;
cout << "sizeof(int) " << sizeof(int) << endl;
cout << "sizeof(double) " << sizeof(double) << endl;
 
cout << endl;
cout << "-------struct" << endl;
cout << "sizeof(s1) " << sizeof(s1) << endl;
cout << "sizeof(s2) " << sizeof(s2) << endl;

运行结果:
在这里插入图片描述
不同机器环境,可能结果不同,但不影响说明问题。例如,结构体s1中包含一个char和int,那么s1的大小应该是5,但结果是8,s2也是如此,这就涉及到一个概念:内存对齐。


2、内存对齐

(1)什么是内存对齐?
看到的一句说明:数据项仅仅能存储在地址是数据项大小的整数倍的内存位置上。


(2)为什么要内存对齐?
1> 硬件原因:一些硬件平台必须要求内存对齐,否则抛出异常;另外涉及到不同平台的移植问题。

2> 软件原因:对齐后访问效率更高。


3、C++98/03 内存对齐实现

此情况下主要是由编译器实现,不同编译器有不同方法。
(1)MSVC

__declspec(align(#)) //其#的内容可以是预编译宏,但不能是编译期数值
#progma pack
__alignof


(2)gcc

 __attribute__((__aligned__((#))))
 __alignof__


4、C++11内存对齐实现

(1)C++11新引入操作符alignof,对齐描述符alignas,基本对齐值alignof(std::max_align_t)

alignas可以接收常量表达式和类型作为参数,可以修饰变量、类的数据成员等,不能修饰位域和用register申明的变量。一般往大对齐。直接看一段代码:

struct s1
{
    char s;
    int i;
};
 
struct s2
{
    int i;
    double d;
};

struct s3
{
    char s;
    double d;
    int i;
};

struct s11
{
    alignas(16) char s;
    int i;
};

struct s12
{
    alignas(16) char s;
    int i;
};

// alignof
cout << "-------------------alignof---------------------" << endl;

// 基本对齐值
cout << "alignof(std::max_align_t)" << alignof(std::max_align_t) << endl;

cout << endl;
cout << "-------basic type" << endl;
cout << "alignof(char)" << alignof(char) << endl;
cout << "alignof(int)" << alignof(int) << endl;
cout << "alignof(double)" << alignof(double) << endl;

cout << endl;
cout << "-------struct" << endl;
cout << "alignof(s1)" << alignof(s1) << endl;
cout << "alignof(s2)" << alignof(s2) << endl;
cout << "alignof(s3)" << alignof(s3) << endl;
cout << endl;
cout << endl;

// alignas
cout << "-------------------alignas---------------------" << endl;
cout << "alignof(s1)" << alignof(s1) << endl;
cout << "alignof(s11)" << alignof(s11) << endl;
cout << "alignof(s12)" << alignof(s12) << endl;


cout << "sizeof(s1)    " << sizeof(s1) << endl;
cout << "sizeof(s11)" << sizeof(s11) << endl;
cout << "sizeof(s12)" << sizeof(s12) << endl;

运行结果:
在这里插入图片描述
(2)C++11还新增了几个内存对齐的函数,每个函数有特定作用
std::alignment_of
std::aligned_storage
std::max_align_t
std::align


5、实例

#include <iostream>
//对齐支持
//C++11标准定义alignof来查看数据的对齐方式
//Microsoft定义为__alignof来查看数据的对齐方式
struct EmptyStruct{};
class EmptyClass{};
class EmptyClass1;
struct HowManyBytes
{
     char a;
     int b;
};

struct ColorVector1
{
     double r;
     double g;
     double b;
     double a;
};

//C++11标准提供修饰符alignas设定struct/class/union的对齐方式
//Microsoft使用_declspec(align(#))来设定struct/class/union对齐方式
struct _declspec(align(32)) ColorVector2    //直接将ColorVector设定在32字节的地址边界上,其起始地址必须是32的倍数
 //等价_declspec(align(32)) struct ColorVector
{
     double r;
     double g;
     double b;
     double a;
};

int main()
{
     std::cout << "sizeof(EmptyStruct): " << sizeof(EmptyStruct) << std::endl;     //1
     std::cout << "sizeof(EmptyClass): " << sizeof(EmptyClass) << std::endl;    //1
     std::cout << "__alignof(EmptyClass): " << __alignof(EmptyClass) << std::endl;    //1

     //error,类型不完整,编译失败
     //std::cout << "__alignof(EmptyClass1): " << __alignof(EmptyClass1) << std::endl;//1
     std::cout << "sizeof(char): " << sizeof(char) << std::endl;    //1
     std::cout << "sizeof(int): " << sizeof(int) << std::endl;    //4
     std::cout << "sizeof(HowManyBytes): " << sizeof(HowManyBytes) << std::endl;    //8
     std::cout << "offset of char a: " << offsetof(HowManyBytes, a) << std::endl;    //0
     std::cout << "offset of int b: " << offsetof(HowManyBytes, b) << std::endl;    //4

     std::cout << "__alignof(HowManyBytes): " << __alignof(HowManyBytes) << std::endl;    //4
     std::cout << "__alignof(ColorVector1): " << __alignof(ColorVector1) << std::endl;    //8
     std::cout << "__alignof(ColorVector2): " << __alignof(ColorVector2) << std::endl;    //32
     std::cout << "sizeof(ColorVector2): " << sizeof(ColorVector2) << std::endl;    //32

     std::cout << "in ColorVector1 offset of double r: " << offsetof(ColorVector1, r) << std::endl;		//0
     std::cout << "in ColorVector1 offset of double g: " << offsetof(ColorVector1, g) << std::endl;    //8
     std::cout << "in ColorVector1 offset of double b: " << offsetof(ColorVector1, b) << std::endl;    //16
     std::cout << "in ColorVector1 offset of double a: " << offsetof(ColorVector1, a) << std::endl;    //24
     std::cout << std::endl;

     std::cout << "in ColorVector2 offset of double r: " << offsetof(ColorVector2, r) << std::endl;		//0
     std::cout << "in ColorVector2 offset of double g: " << offsetof(ColorVector2, g) << std::endl;    //8
     std::cout << "in ColorVector2 offset of double b: " << offsetof(ColorVector2, b) << std::endl;    //16
     std::cout << "in ColorVector2 offset of double a: " << offsetof(ColorVector2, a) << std::endl;    //24

     int a;
     long long b;
     auto &c = b;
     char d[1024] = { 0 };


     //对内置类型
     std::cout << __alignof(int) << std::endl;    //4

     //对变量、引用或者数组
     std::cout << __alignof(a) << std::endl    //4
          << __alignof(b) << std::endl    //8
          << __alignof(c) << std::endl    //8  引用与其引用的数据对齐值相同
          << __alignof(d) << std::endl;    //1 数组的对齐值由其元素决定

     return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值