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;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
高质量C++-C编程指南 目 录 前 言... 6 第1章 文件结构... 11 1.1 版权和版本的声明... 11 1.2 头文件的结构... 12 1.3 定义文件的结构... 13 1.4 头文件的作用... 13 1.5 目录结构... 14 第2章 程序的版式... 15 2.1 空行... 15 2.2 代码行... 16 2.3 代码行内的空格... 17 file:///D|/My Documents/学习/高质量C++-C编程指南.txt[2008-11-11 21:48:26] 2.4 对齐... 18 2.5 长行拆分... 19 2.6 修饰符的位置... 19 2.7 注释... 20 2.8 类的版式... 21 第3章 命名规则... 22 3.1 共性规则... 22 3.2 简单的Windows应用程序命名规则... 23 3.3 简单的Unix应用程序命名规则... 25 第4章 表达式和基本语句... 26 4.1 运算符的优先级... 26 4.2 复合表达式... 27 4.3 if 语句... 27 4.4 循环语句的效率... 29 4.5 for 语句的循环控制变量... 30 4.6 switch语句... 30 4.7 goto语句... 31 第5章 常量... 33 5.1 为什么需要常量... 33 5.2 const 与 #define的比较... 33 5.3 常量定义规则... 33 5.4 类中的常量... 34 第6章 函数设计... 36 6.1 参数的规则... 36 6.2 返回值的规则... 37 6.3 函数内部实现的规则... 39 6.4 其它建议... 40 6.5 使用断言... 41 6.6 引用与指针的比较... 42 file:///D|/My Documents/学习/高质量C++-C编程指南.txt[2008-11-11 21:48:26] 第7章 内存管理... 44 7.1内存分配方式... 44 7.2常见的内存错误及其对策... 44 7.3指针与数组的对比... 45 7.4指针参数是如何传递内存的?... 47 7.5 free和delete把指针怎么啦?... 50 7.6 动态内存会被自动释放吗?... 50 7.7 杜绝“野指针”... 51 7.8 有了malloc/free为什么还要new/delete ?... 52 7.9 内存耗尽怎么办?... 53 7.10 malloc/free 的使用要点... 54 7.11 new/delete 的使用要点... 55 7.12 一些心得体会... 56 第8章 C++函数的高级特性... 57 8.1 函数重载的概念... 57 8.2 成员函数的重载、覆盖与隐藏... 60 8.3 参数的缺省值... 63 8.4 运算符重载... 64 8.5 函数内联... 65 8.6 一些心得体会... 68 第9章 类的构造函数、析构函数与赋值函数... 69 9.1 构造函数与析构函数的起源... 69 9.2 构造函数的初始化表... 70 9.3 构造和析构的次序... 72 9.4 示例:类String的构造函数与析构函数... 72 9.5 不要轻视拷贝构造函数与赋值函数... 73 9.6 示例:类String的拷贝构造函数与赋值函数... 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数... 75 9.8 如何在派生类中实现类的基本函数... 75 file:///D|/My Documents/学习/高质量C++-C编程指南.txt[2008-11-11 21:48:26] 9.9 一些心得体会... 77 第10章 类的继承与组合... 78 10.1 继承... 78 10.2 组合... 80 第11章 其它编程经验... 82 11.1 使用const提高函数的健壮性... 82 11.2 提高程序的效率... 84 11.3 一些有益的建议... 85 参考文献... 87 附录A :C++/C代码审查表... 88 附录B :C++/C试题... 93 附录C :C++/C试题的答案与评分标准... 97 前 言
目 录 前 言 6 第1章 文件结构 11 1.1 版权和版本的声明 11 1.2 头文件的结构 12 1.3 定义文件的结构 13 1.4 头文件的作用 13 1.5 目录结构 14 第2章 程序的版式 15 2.1 空行 15 2.2 代码行 16 2.3 代码行内的空格 17 2.4 对齐 18 2.5 长行拆分 19 2.6 修饰符的位置 19 2.7 注释 20 2.8 类的版式 21 第3章 命名规则 22 3.1 共性规则 22 3.2 简单的WINDOWS应用程序命名规则 23 3.3 简单的UNIX应用程序命名规则 25 第4章 表达式和基本语句 26 4.1 运算符的优先级 26 4.2 复合表达式 27 4.3 IF 语句 27 4.4 循环语句的效率 29 4.5 FOR 语句的循环控制变量 30 4.6 SWITCH语句 30 4.7 GOTO语句 31 第5章 常量 33 5.1 为什么需要常量 33 5.2 CONST 与 #DEFINE的比较 33 5.3 常量定义规则 33 5.4 类中的常量 34 第6章 函数设计 36 6.1 参数的规则 36 6.2 返回值的规则 37 6.3 函数内部实现的规则 39 6.4 其它建议 40 6.5 使用断言 41 6.6 引用与指针的比较 42 第7章 内存管理 44 7.1内存分配方式 44 7.2常见的内存错误及其对策 44 7.3指针与数组的对比 45 7.4指针参数是如何传递内存的? 47 7.5 FREE和DELETE把指针怎么啦? 50 7.6 动态内存会被自动释放吗? 50 7.7 杜绝“野指针” 51 7.8 有了MALLOC/FREE为什么还要NEW/DELETE ? 52 7.9 内存耗尽怎么办? 53 7.10 MALLOC/FREE 的使用要点 54 7.11 NEW/DELETE 的使用要点 55 7.12 一些心得体会 56 第8章 C++函数的高级特性 57 8.1 函数重载的概念 57 8.2 成员函数的重载、覆盖与隐藏 60 8.3 参数的缺省值 63 8.4 运算符重载 64 8.5 函数内联 65 8.6 一些心得体会 68 第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始化表 70 9.3 构造和析构的次序 72 9.4 示例:类STRING的构造函数与析构函数 72 9.5 不要轻视拷贝构造函数与赋值函数 73 9.6 示例:类STRING的拷贝构造函数与赋值函数 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数 75 9.8 如何在派生类中实现类的基本函数 75 9.9 一些心得体会 77 第10章 类的继承与组合 78 10.1 继承 78 10.2 组合 80 第11章 其它编程经验 82 11.1 使用CONST提高函数的健壮性 82 11.2 提高程序的效率 84 11.3 一些有益的建议 85 参考文献 87 附录A :C++/C代码审查表 88 附录B :C++/C试题 93 附录C :C++/C试题的答案与评分标准 97
课程目标本课程详细讲解了C++的所有关键字,包括C++11和C++20新增的关键字和语言特性适用人群本课程并非零基础,适合有C语言基础,尤其是学过嵌入式linux核心课程的《C语言高级专题》的同学。课程简介《跟朱老师从C高级到征服C++》属于系列课程《朱有鹏老师热门编程语言全解》的第一部分,主要针对C++语言完全学习。本课程可以看做是嵌入式linux核心课程中《C语言高级专题》课程的延续,在学好了C语言前提下继续深度学习C++语言。整个课程共分为5部分。涵盖了C++基础语法和使用,面向对象,STL与泛型,Boost库和设计模式,C++编程优化技巧等非常广泛的内容,是市面上非常缺少的深度完整学习C++,培养编程技能和修养的一套系列学习课程。整个课程预计2020年底前录制完成,总时长预计150-200小时。朱老师C++第1部分-从C到C++朱老师C++第2部分-C++和面向对象朱老师C++第3部分-STL等高阶话题朱老师C++第4部分-Boost库和设计模式朱老师C++第5部分-C++编程优化课程特色*完全零基础,降低学习门槛。*深入浅出,通俗易懂。不怕学不会,就怕你不学习。*思路清晰、语言风趣,对着视频看也不会想睡觉······*视频 + 文档 + 练习题 + 答疑,全方位保证学习质量。*基础知识 + 思路引导的教学方式,授之以鱼更授之以渔。*系列课程。本教程只是入门篇,后续还有更多更精彩视频更新中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值