Cherno C++ P67 C++的联合体(union)

news/2024/11/28 17:56:27/

YouTube视频链接

C++的联合体(union)

本文是ChernoP67视频的学习笔记。
  联合体有点像类类型,或者结构体类型。只不过它一次只能占用一个成员的内存。若我们有一个结构体声明了4个浮点数,则有16个字节在这个结构体中。若用联合体声明声明4个浮点数,联合体的大小仍然是4个字节。我们可以给联合体添加静态函数或者普通函数或者方法等等,但不能使用虚方法。
  通常使用联合体是和类型双关紧密相关的,当想给一个变量取两个不同的名字时非常有用。通常union是匿名使用的,但是匿名union不能含有成员函数。如下代码。

#include<iostream>int main()
{struct Union{union{float a;int b;};};Union u;u.a = 2.0f;std::cout << u.a << "," << u.b << std::endl;std::cin.get();
}

  按F5运行代码得到2和107xxxx,因为107xxxx是浮点数形式的2字节表示,就好像取了组成浮点数的内存,然后把它解释成一个模型,这就是类型双关了。

在这里插入图片描述
  如下代码有Vector2,Vector4结构体,还有一个函数PrintVector2,参数是vector,然后将其打印。

#include<iostream>struct Vector2
{float x, y;
};
struct Vector4
{float x, y, z, w;
};void PrintVector2(const Vector2& vector)
{std::cout << vector.x << "," << vector.y << std::endl;
}
int main()
{std::cin.get();
}

  Vector4实际上是2个Vector2,所以构造一个Vector2,给它一些参数,返回整个对象,但是这会创建一个全新的对象,所以可以返回一个指向Vector2的引用,引用的x是一个类型双关的版本,我们要做的就是把x的内存地址转换成Vector2,然后解引用。

struct Vector4
{float x, y, z, w;Vector2& GetA(){return *(Vector2*)&x;}
};

  另一种方法是使用union,这是一个匿名union,因为union只有一个成员,所以x,y,z,w会占用相同的空间,我们把它包装在一个匿名结构体中。现在这个结构体是union的一个成员,这是一个16字节的结构体。我们创建一个Vector4,可以正常访问vector.x并把它设为2.0f。

#include<iostream>struct Vector2
{float x, y;
};struct Vector4
{union{struct{float x, y, z, w;};};
};void PrintVector2(const Vector2& vector)
{std::cout << vector.x << "," << vector.y << std::endl;
}int main()
{Vector4 vector = { 1.0f,2.0f,3.0f,4.0f };vector.x = 2.0f;std::cin.get();
}

  若给结构体取了名字A,则会报错。但如果它是匿名的,它只是一种数据结构,没有添加任何东西。这里的好处是它将所有变量转换成单个单元,这就是union所期望做的事。
在这里插入图片描述  若继续创建一个结构体,向union添加了第二个成员,它和第一个元素占据相同的空间,它有两个Vector2组成。

struct Vector2
{float x, y;
};struct Vector4
{union{struct {float x, y, z, w;};struct{Vector2 a, b;};};
};

  现在有几种访问Vector4内数据的方法,可以用xywz或者ab,a和xy的内存是一样的,b和zw的内存一样。如下代码


int main()
{Vector4 vector = { 1.0f,2.0f,3.0f,4.0f };PrintVector2(vector.a);PrintVector2(vector.b);vector.z = 500.0f;std::cout << "------------------" << std::endl;PrintVector2(vector.a);PrintVector2(vector.b);vector.x = 2.0f;std::cin.get();
}

在这里插入图片描述
  虽然没有碰过vector里b的部分,设置的是z=500,但它们占用了相同的内存。


http://www.ppmy.cn/news/243837.html

相关文章

(P67-71)数据库系统下-基于时间戳的并发控制

文章目录 1.什么是时间戳&#xff1f;2.基于时间戳的并发控制3.基于时间戳的另一种调度规则4.基于有效性确认的并发控制方法5.小结 1.什么是时间戳&#xff1f; 不用锁&#xff0c;能否进行并发控制&#xff1f; 时间戳(TIMESTAMP) 一种基于时间的标志&#xff0c;将某一时刻…

SpringBoot2:开发实用篇(黑马程序员P67~P142)

一、热部署 1.1 手动启动热部署 1.2 自动启动热部署 1.3 热部署范围配置 1.4 关闭热部署功能 二、配置高级 2.1 ConfigurationProperties 2.2 EnableConfigurationProperties 2.3 松散绑定 2.4 常用计量单位应用 2.5 bean属性校验 2.6 yaml语法规则 三、测试 3.1 加载测试专用…

Cherno C++系列笔记23——P66~P67 类型双关、联合体union

文章目录 1.P66 类型双关1.1.实例11.2.实例2 2.P67 联合体union2.1.实例12.2.实例22.2.1.使用类型双关&#xff08;指针类型重解释&#xff09;2.2.2.使用联合体union 1.P66 类型双关 参考&#xff1a;视频 笔记 类型双关用来在C中绕过类型系统。C中有类型系统&#xff0c;当…

干货 | PostgreSQL 中的多版本并发控制

大部分的数据库系统都使用锁定来进行并发控制&#xff0c;而 PostgreSQL 的做法就略有不同。它使用多版本模型&#xff08;也称为多版本并发控制&#xff0c;Multi-Version Concurrency Control&#xff0c;简称 MVCC&#xff09;来维持数据的一致性。因此&#xff0c;在查询数…

Redis进阶:缓存穿透|缓存击穿|缓存雪崩问题

Redis应用问题 1. 缓存穿透问题1.1 问题描述1.2 解决方案方法一&#xff1a;空值缓存方法二&#xff1a;设置可访问的名单&#xff08;白名单&#xff09;方法三&#xff1a;采用布隆过滤器方法四&#xff1a;进行实时监控 2. 缓存击穿问题2.1 问题描述2.2 解决方案方法一&…

Java单元测试学习(二)

Java单元测试学习&#xff08;二&#xff09; 使用测试框架JUnitMockito和单元测试覆盖率框架JaCoCo 目录结构 依赖—很好&#xff0c;这里又有个小插曲 打开页面查看覆盖率时一直显示0/0---->最后的解决方式是①添加了maven-surefire-plugin插件 <?xml version&quo…

Linux内核文件写入流程

文本代码基于Linux 5.15 。 当用户层调用write 去做写入&#xff0c; linux 内核里面是如何处理的&#xff1f; 本文以exfat 为例&#xff0c; 讨论这个流程 入口函数 write 系统调用的定义如下&#xff1a; fs/read_write.c ssize_t ksys_write(unsigned int fd, const ch…

亚信科技 HVV面试复盘

亚信科技 HVV面试复盘 1.想做研判还是监测2.去年的国护厂商是什么3.天眼常见的日志检索的命令4.客户部署了负载均衡,流量是先通过负载服务器再到天眼上面的,这种情况怎么溯源找到它的原始攻击IP呢5.如果天眼中的日志检索流量包中不带xff字段呢6.weblogic都有那些漏洞7.文件上…