关于C++内存对齐


C++11从标准层面引入了一些和内存对齐相关的特性,标准库也增加了对应的组件,这里稍微总结一下。

取得某个类型的对齐值

C++中的Object(对象)是指一块满足以下条件的内存区域:

  1. 具有size属性,即能用sizeof取其大小。
  2. 具有alignment属性,即能用alignof取其对齐量。这个在稍后有详细的阐述。
  3. 类型
  4. ……(lifetime等)

现在已经知道了每个对象都有其类型,这样的类型称为“对象类型”(object type)。每个对象类型都有一个alignment值,该值的类型为std::size_t,且总为2的整数次幂。我们可以通过关键字alignof或标准库中的std::alignment_of(声明位于头文件<type_traits>)获知此值,比如:

struct S { char a; double b }
int main(void)
{
cout << alignof(S) << endl;
cout << alignment_of<int>::value << endl;
}

C++17引入了std::alignment_of_v,允许这样的写法:

int main(void)
{
cout << alignment_of_v<double> << endl;
}

当然,只是语法糖而已。

指定类型的对齐规则

C++11引入了关键字alignas用于修饰类型,它有以下三种使用形式:

  1. alignas(expr),这里expr必须是一个编译期常量表达式,且应为2的整数次幂。
  2. alignas(Type),这个写法等价于alignas(alignof(Type))
  3. alignas(pack...),这里pack是个模板参数包,相当于对参数包中的每个元素P,同时以alignas(P)来修饰后面的类型。

下面看例子:

struct alignas(16) MyStruct
{
char ch;
}; int main(void)
{
MyStruct instanceOfMyStruct; //instanceOfMyStruct按16字节对齐
alignas(127 + 1) char charArray[128]; //charArray按128字节对齐
alignas(int) char ch; //ch按alignof(int)字节对齐
//...
}

堆上对象的内存对齐

我们已经能够指定某个类型的对齐规则了,但对于堆上申请下来的对象还缺乏控制。我们当然可以基于malloc自己写一个,不过已经有下面的几种方案:

  1. operator new允许通过一个std::align_val_t类型的参数来显示给出对齐要求,然而这是C++17才引入的,暂时没法广泛使用。
  2. 二段式构造。先调用_aligned_malloc(Windows)或者posix_memalign(Posix)拿到一块内存,然后用placement new构造对象。

其他

C++11引入的std::aligned_storage(头文件<type_traits>中)用于获得一块按指定规则对齐的内存块。它相当于:

template<std::size_t Len, std::size_t Align>
struct aligned_storage
{
struct type
{
alignas(Align) unsigned char data[Len];
};
};

C++11引入的std::max_align_t:“std::max_align_t is a trivial type whose alignment requirement is at least as strict (as large) as that of every scalar type”,也就是任何一个scalar type的默认对齐大小都不会超过alignof(max_align_t)

关于C++内存对齐的更多相关文章

  1. C++内存对齐总结

    大家都知道,C++空类的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址.非空类的大小与类中非静态成员变量和虚函数表的多少有关. 而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有 ...

  2. C/C++: C++位域和内存对齐问题

    1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...

  3. C/C++ 知识点1:内存对齐

    预备知识:基本类型占用字节 在32位操作系统和64位操作系统上,基本数据类型分别占多少字节呢? 32位操作系统: char : 1    int :4    short : 2    unsigned ...

  4. Windows+GCC下内存对齐的常见问题

    结构/类对齐的声明方式 gcc和windows对于modifier/attribute的支持其实是差不多的.比如在gcc的例子中,内存对齐要写成: class X { //... } __attrib ...

  5. c++内存对齐

    内存对齐原则: 1.数据成员对齐规则:struct, union的数据成员,第一个数据成员放在offset为0的地方,之后的数据成员的存储起始位置都是放在该数据成员大小的整数倍位置.如在32bit的机 ...

  6. C语言中内存对齐

    今天一考研同学问我一个问题,一个结构体有一个int类型成员和一个char类型成员,问我这个结构体类型占多少个字节,我直接编个程序给他看结果.这个结构体占八个字节,咦,当时我蛮纳闷的,一个int类型四个 ...

  7. 内存对齐 和 sizeof小结

    数据对齐(内存对齐)指该数据所在的地址必须是该数据长度的整数倍.X86CPU能直接访问对齐的数据,当它试图访问未对齐的数据时,会在内部进行一系列的调整,降低运行速度.数据对齐一般出现在结构体和类中,在 ...

  8. 解析C语言结构体对齐(内存对齐问题)

    C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...

  9. C语言再学习之内存对齐

    昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...

  10. C结构体中数据的内存对齐问题

    转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...

随机推荐

  1. [Ubuntu]18终止程序运行

    方法: 一.使用命令 killall  (使用方便,但要知道卡死应用程序的名称) 二.使用 gnome-system-monitor (不知道卡死应用程序的名称,也可以慢慢找出) 操作步骤: step ...

  2. 利用Smarty实现文本隔行变色

    行变色 php页面 <?phpinclude "libs/Smarty.class.php";$smarty = new Smarty(); $link = mysql_co ...

  3. FastDFS 学习总结

    1.1   什么是FastDFS FastDFS是用c语言编写的一款开源的分布式文件系统.FastDFS为互联网量身定制,充分考虑了冗余备份.负载均衡.线性扩容等机制,并注重高可用.高性能等指标,使用 ...

  4. 数据库版本管理工具--Flyway的使用

    软件开发正常流程是:开发环境 ---> 测试环境  ----> 产环境 在开发过程中经常需要变更数据库: 表结构变更. 基础数据变更. 最直接的做法是:用客户端连上数据库直接修改. 依次修 ...

  5. Docker save and load镜像保存

    持久化docker的镜像或容器的方法 Docker的镜像和容器可以有两种方式来导出 docker save #ID or #Name docker export #ID or #Name docker ...

  6. Jmeter启动报错解决方案

    安装好jmeter之后在启动Jmeter的过程中出现了如下的报错信息(大部分的原因是配置不对): /usr/local/Cellar/jmeter/5.1.1/libexec/bin/jmeter: ...

  7. web系统认证与鉴权中的一些问题

    认证鉴权系统的初心: 空间管理: 1.他是谁? 他登陆了没有? 2.他要做什么? 2.1 他要使用什么功能? 他是否有这个功能的权限. 2.2 他要使用这个功能做什么操作? 他是否有这个功能的这个操作 ...

  8. Unity小白文——单例的定义

    当类继承与MonoBehaviour时 public class TestSingle : MonoBehaviour { public static TestSingle Instance; voi ...

  9. 【VS开发】【Live555-rtsp】在windows 使用vs2008编译live555

    在windows 使用vs2008编译live555 基于 liveMedia的程序,需要通过继承UsageEnvironment抽象类和TaskScheduler抽象类,定义相应的类来处理事件调度, ...

  10. 【VS开发】【计算机视觉】使用opencv静态库编译程序时爆出错误的解决方案

    #[VS开发][计算机视觉]关于opencv静态库的使用说明 标签:[VS开发] [图像处理] --- 忽然间发现OpenCV中居然有已经编译好的静态链接库,于是尝试着使用一下,却遇到了比较多的问题, ...