码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • C++11alignas 说明符和alignof 运算符和内存对齐问题


    alignas 说明符

    语法

    alignas( 表达式 )
    alignas( 类型标识 )
    alignas( 包 ... )

    1) 表达式 必须是求值为零或合法的对齐或扩展对齐的整型常量表达式。

    2) 等价于 alignas(alignof(类型标识))

    3) 等价于对同一说明应用多个 alignas 说明符,逐个对应于形参包的各个成员,形参包可以是类型或非类型形参包。

    解释

    alignas 说明符可用于:

    • 类的声明或定义;
    • 非位域类数据成员的声明;
    • 变量声明,除了它不能应用于下列内容:
      • 函数形参;
      • catch 子句的异常形参。

    这种声明所声明的对象或类型的对齐要求https://zh.cppreference.com/w/cpp/language/object#.E5.AF.B9.E9.BD.90(即 每个对象类型都具有被称为对齐要求(alignment requirement)的性质,它是一个整数(类型是 std::size_t,总是 2 的幂),表示这个类型的不同对象所能分配放置的连续相邻地址之间的字节数。)

    将等于用于该声明的所有 alignas 说明符中最严格(最大)的非零 表达式,除非这会削弱类型的自然对齐。

    如果某个声明上的最严格(最大)alignas 比当它没有任何 alignas 说明符的情况下本应有的对齐更弱(即弱于其原生对齐,或弱于同一对象或类型的另一声明上的 alignas),那么程序非良构:

    1. struct alignas(8) S {};
    2. struct alignas(1) U { S s; }; // 错误:如果没有 alignas(1) 那么 U 的对齐将会是 8

    无效的非零对齐,例如 alignas(3) 非良构。

    同一声明上,比其他 alignas 弱的有效的非零对齐被忽略。

    始终忽略 alignas(0)。

    alignof 运算符

    查询类型的对齐要求。

    语法

    alignof( 类型标识 )

    返回 std::size_t 类型的值。

    解释

    返回由类型标识所指示的类型的任何实例所要求的对齐字节数,该类型可以是完整对象类型、元素类型完整的数组类型或者到这些类型之一的引用类型。

    如果类型是引用类型,那么运算符返回被引用类型的对齐要求;如果类型是数组类型,那么返回元素类型的对齐要求。

    1. #include
    2. struct Foo
    3. {
    4. int i;
    5. float f;
    6. char c;
    7. };
    8. // 注:下面的 `alignas(alignof(long double))`
    9. // 如果需要可以简化为 `alignas(long double)`
    10. struct alignas(long double) Foo2//这里其实就是相当于设置了内存对齐为8了
    11. {
    12. // Foo2 成员的定义...
    13. };
    14. struct Empty {};
    15. struct alignas(64) Empty64 {};
    16. int main()
    17. {
    18. std::cout << "对齐字节数" "\n"
    19. "- char :" << alignof(char) << "\n"
    20. "- 指针 :" << alignof(int*) << "\n"
    21. "- Foo 类 :" << alignof(Foo) << "\n"
    22. "- Foo2 类 :" << alignof(Foo2) << "\n"
    23. "- 空类 :" << alignof(Empty) << "\n"
    24. "- 带 alignas(64) 的空类:" << alignof(Empty64) << "\n";
    25. std::cout << "- Foo 类字节大小 : " << sizeof(Foo) << "\n";
    26. }

        我们要区分sizeof和alignof,sizeof运算符获取字节大小,alignof获取的是对齐

    空类

    很多人认为空类大小就是1,看过我们上面aligas后估计会想到可以用这个设置一下,但这都是不是什么重点,我们来强调一下概念。

    为保证同一类型的不同对象地址始终有别,要求任何对象或成员子对象的大小至少为 1,即使该类型是空的类类型(即没有非静态数据成员的 class 或 struct)(,除非带有 [[no_unique_address]]) (C++20 起)。

    1. #include
    2. #include
    3. struct Base {}; // 空类
    4. struct Derived1 : Base {
    5. };
    6. struct Derived3 : Base {
    7. Derived1 c; // 从 Base 派生,占用 sizeof(int) 字节
    8. int i;
    9. };
    10. struct Empty {}; // 空类
    11. struct X {
    12. int i;
    13. [[no_unique_address]] Empty e;/*如果空成员子对象使用属性 [[no_unique_address]],那么允许像空基类一样优化掉它们。取这种成员的地址会产生可能等于同一个对象的某个其他成员的地址*/
    14. };
    15. int main()
    16. {
    17. std::cout << sizeof(Derived1) << std::endl;//正常的1,优化空基类
    18. std::cout << sizeof(Derived3) << std::endl;//正常的8,空基类优化掉,4+1,对齐就是8
    19. std::cout << sizeof(X) << std::endl;//文档的说法是”允许优化掉“,那么打印的是4,但MSVC并没有这么做,还是8(GCC是4),注意这是c++20的
    20. }

    c++20这个属性不会的可以先不看,总而言之就是,要求至少为1,没说为1,凡事严谨点总是好的。

    总结一下就是,说起空类的大小,你首先要考虑有没有alignas,有没有[[no_unique_address]],然后就能说“多数情况下,是1”

    总结

    qq交流群:829810543  回复:C++ 

    alignas 说明符 (C++11 起) - cppreference.comhttps://zh.cppreference.com/w/cpp/language/alignasalignof 运算符(C++11 起) - cppreference.comhttps://zh.cppreference.com/w/cpp/language/alignof 对象 - cppreference.comhttps://zh.cppreference.com/w/cpp/language/object#.E5.AF.B9.E9.BD.90空基类优化 - cppreference.comhttps://zh.cppreference.com/w/cpp/language/ebo

  • 相关阅读:
    Java微信小程序奶茶在线预定点单系统 uniapp小程序
    外汇天眼:亏亏亏,为什么亏损的总是我?大数据分析报告告诉你答案
    NPM常用命令
    Maven进阶-配置私服(Nexus 的使用)
    向NXP官网Linux内核添加ALPHA开发板
    dubbo配置及其属性参考文件,配置参考手册
    【工具门户】Backstage配置使用PostgreSQL(三)
    Git(第一篇)——Git的下载与安装(史上最全最详细)
    机器学习策略篇:详解如何改善你的模型的表现(Improving your model performance)
    2023年天津农学院专升本专业课参考教材
  • 原文地址:https://blog.csdn.net/a4364634611/article/details/127777485
  • 最新文章
  • 【JVM】编译执行与解释执行的区别是什么?JVM 使用哪种方式?
    用 Hashids 优雅解决 C 端自增 ID 暴露问题
    V8引擎 精品漫游指南--Ignition篇(上) 指令 栈帧 槽位 调用约定 内存布局 基础内容
    LLVM Pass快速入门(四):代码插桩
    milkup:桌面端 markdown AI续写和即时渲染
    基于项目工程构建SBOM(软件物料清单)的研究
    鸿蒙应用开发UI基础第二节:鸿蒙应用程序框架核心解析与实操
    .NET 中如何快速实现 List 集合去重?
    扣子Coze实战:从0到1打造抖音+小红书热点监控智能体
    浅谈数据访问层
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号