C++初学者指南第一步---13.聚合类型

news2025/1/17 6:08:15

C++初学者指南第一步—13.聚合类型

文章目录

  • C++初学者指南第一步---13.聚合类型
    • 1. 类型分类(简化)
    • 2. 如何定义和使用
    • 3. 为什么选择自定义类型/数据聚合?
    • 4. 聚合类型初始化
    • 5.混合
    • 6. 复制
    • 7. 值和引用的语义
    • 8.聚合的向量(std::vector)
    • 9.最令人烦恼的解析

1. 类型分类(简化)

基本类型void, bool, char, int, double, …
void、bool、char、int、double、…
简单聚合主要用途:对数据进行分组
聚合:可能包含一个/多个基本类型或其他兼容的聚合类型
无法控制组成类型的相互作用
简单,(编译器生成的)默认构造/析构/复制/赋值。
标准的内存布局(所有成员按照声明顺序连续布置),如果所有成员具有相同的访问控制(例如全部为public)。
更复杂的自定义类型自定义不变量和对成员相互作用的控制
限制成员访问
具有成员函数
用户自定义构造/成员初始化
用户自定义的析构 / 复制 / 赋值
可以是多态的(包含虚成员函数)

2. 如何定义和使用

示例:具有 2 个整数坐标的类型
代码段1

struct point {
  int x;  // ← "成员变量"
  int y; 
};
// 创建新对象 (在栈中)
point p {44, 55}; 
// 打印成员变量的值
cout << p.x <<' '<< p.y;  // 44 55

分配给成员变量值:(代码段2)

p.x = 10;
p.y = 20;
cout << p.x <<' '<< p.y;  // 10 20

成员变量的存储顺序与声明顺序相同。
代码段1的内存:
在这里插入图片描述
代码段2的内存:
在这里插入图片描述
运行上面代码

3. 为什么选择自定义类型/数据聚合?

接口变得更易于正确使用

  • 语义数据分组: 点,日期…
  • 避免了许多函数参数,从而减少了混乱。
  • 函数可以使用一个专门的类型来返回多个值,而不是使用多个非常量引用输出参数。

不使用则会有糟糕的接口:

void closest_point_on_line (double lx2, double ly1, double lx2i, double ly2, double px, double py, double& cpx, double& cpy) { … }
  • 许多相同类型的参数⇒容易编写错误
  • 非常量引用输出参数 ⇒ 容易出错
  • 线的内部表示也被嵌入到接口中

使用则好多了:

struct point { double x; double y; };
struct line  { point a; point b; };
point closest_point_on_line (line const& l, point const& p) { … }
  • 直接明了的接口
  • 易于正确使用
  • 如果线的内部表示更改了(例如,点+方向而不是2个点)⇒ 需要改变closest_point_on_line的实现方式,但其接口可以保持不变⇒ 大多数调用代码无需更改!

4. 聚合类型初始化

语法:

Type { arg1, arg2, …, argN }
  • 花括号括起来的成员值列表
  • 按成员声明顺序排列
enum class month {jan = 1, feb = 2,…, dec = 12};
struct date {
  int yyyy;
  month mm;
  int dd;
};
int main () {
  date today {2020, month::mar, 15};	
  // C++98的写法,依然正确:
  date tomorrow = {2020, month::mar, 16};	
}

5.混合

示例:作为 person 成员的日期

enum class month { jan=1, feb=2,, dec=12 };
struct date {   
  int yyyy;
  month mm;
  int dd;
};
struct person {
  std::string name;
  date bday;
};
int main () {
  person jlp { "Jean-Luc Picard", {2305, month::jul, 13} };
  cout << jlp.name;     // Jean-Luc Picard
  cout << jlp.bday.dd;  // 13
  date yesterday { 2020, month::jun, 16 };
  person rv = { "Ronald Villiers", yesterday };
}

运行上面代码

6. 复制

副本总是所有成员的深层拷贝!

enum class month {jan = 1,};
struct date { 
  int yyyy;  month mm;  int dd; 
};
int main () {
  date a {2020, month::mar, 7};     
  date b = a;  // deep copy of a
  b.dd = 22;   // change b
}

main 函数最后一行后的状态:
在这里插入图片描述
拷贝构造 = 创建一个具有与源相同值的新对象
拷贝赋值 = 使用源对象的值覆盖现有对象的值

struct point { int x; int y; };
point p1 {1, 2};  // 构造
point p2 = p1;    // 拷贝构造
point p3 ( p1 );  // 拷贝构造
point p4 { p1 };  // 拷贝构造
auto  p5 = p1;    // 拷贝构造
auto  p6 ( p1 );  // 拷贝构造
auto  p7 { p1 };  // 拷贝构造
p3 = p2;  // 拷贝赋值
          // (p2和p3之前都存在)

7. 值和引用的语义

值语义
= 变量是指对象本身:

  • 深拷贝:生成一个新的、独立的对象;对象(成员)的值被复制。
  • 深度赋值:使目标的值等于源对象的值。
  • 深度所有权:成员变量引用与包含对象生命周期相同的对象。
  • 基于值的比较:如果它们的值相等,则变量相等。

值语义是几乎所有编程语言中基本类型(int、double等)的默认行为,也是C++中聚合类型/用户自定义类型的默认行为。

引用语义
= 变量是对对象的引用:

  • 浅层复制:变量的副本引用同一对象。
  • 浅层赋值:赋值使变量引用不同的对象。
  • 浅层所有权:成员变量也只是引用。
  • 基于身份的比较:如果变量引用同一对象,则比较相等。

大多数其他主流语言(Java、Python、C#、Swift 等) 对用户自定义类型使用(内置)引用语义。
C++ 的情况是一致的,能够提供全面的控制:

  • 默认情况下:所有类型都采用值语义(除了C风格数组)。
  • 所有类型都可以使用可选的引用语义(通过引用或指针)来实现。

8.聚合的向量(std::vector)

值语义 ⇒

  • vector 的存储包含类型 T 的对象本身,而不仅仅是对它们的引用或指针(就像在 Java/C#/… 中一样)。
  • 如果向量对象被释放 ⇒ 包含的 T 对象也会被释放。
vector v { 0,1,2,3,4 };在这里插入图片描述
struct p2d { int x; int y; };
vector v {{1,2},{5,6},{8,9}};
在这里插入图片描述

9.最令人烦恼的解析

无法使用空括号进行对象构造,因为在C++语法中存在歧义。
在这里插入图片描述

struct A { ... };
A a();  // 声明了一个函数 'a'
        // 没有参数
        // 返回类型为 'A'
A a;    // 构造了一个 A 类型的对象
A a{}  // 也构造了一个 A 类型的对象

附上原文地址
如果文章对您有用,请随手点个赞,谢谢!^_^

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1853420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python使用pywebview打造一个现代化的可视化GUI界面

&#x1f308;所属专栏&#xff1a;【python】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的…

不使用ES,如何使用MySQL实现模糊匹配

1.业务场景 例如&#xff1a;我们实现一个公司的申请审批流程&#xff0c;整个业务流程涉及到两种角色&#xff0c;分别是商务角色与管理员角色&#xff0c;整个流程如下图所示&#xff1a; 核心流程总结为一句话&#xff1a;商务角色申请添加公司后由管理员进行审批。 商务在…

Android中如何动态的调整Dialog的背景深暗

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 在 Android 开发中&#xff0c;当你使用 Dialog 或 DialogFragment 时&#xff0c;可以通过设置 Window 的背景变暗来突出它的可见性。这个效果…

数据虚拟化、Data Fabric(数据编织)的兴起,对数据管理有何帮助?

数字化时代&#xff0c;虚拟化&#xff08;Virtualization&#xff09;并不是一个很陌生的词汇&#xff0c;它是现代数据中心资源管理的核心技术之一&#xff0c;是对 IT 资源&#xff08;如服务器、存储设备、网络设备等&#xff09;的抽象&#xff0c;通过屏蔽 IT 资源的物理…

C语言入门4-函数和程序结构

函数举例 读取字符串&#xff0c;如果字符串中含有ould则输出该字符串&#xff0c;否则不输出。 #include <stdio.h>// 函数声明 int getLine(char s[], int lim); int strindex(char s[], char t[]);int main() {char t[] "ould"; // 要查找的目标子字符串…

windows和linux路径斜杆转换脚本,打开即用

前言&#xff1a; windows和linux的目录路径斜杆是相反的&#xff0c;在ssh或者其他什么工具在win和ubuntu传文件时候经常需要用到两边的路径&#xff0c;有这个工具就不用手动去修改斜杆反斜杠了。之前有个在线网站&#xff0c;后来挂了&#xff0c;就想着自己搞一个脚本来用。…

批量重命名神器揭秘:一键实现文件夹随机命名,自定义长度轻松搞定!

在数字化时代&#xff0c;我们经常需要管理大量的文件夹&#xff0c;尤其是对于那些需要频繁更改或整理的文件来说&#xff0c;给它们进行批量重命名可以大大提高工作效率。然而&#xff0c;传统的重命名方法既繁琐又耗时&#xff0c;无法满足高效工作的需求。今天&#xff0c;…

【C++】初始化列表、匿名对象、static成员、友元、内部类

文章目录 一、初始化列表构造函数体赋值初始化列表explicit关键字 二、匿名对象三、static成员四、友元友元函数友元类 五、内部类六、练习题 一、初始化列表 构造函数体赋值 实际上&#xff0c;构造函数的函数体内&#xff0c;并不是对 对象 初始化的地方&#xff0c;而是对…

电子杂志制作的必备软件:轻松提升制作效率

​电子杂志作为一种新型的媒体形式&#xff0c;具有互动性强、内容丰富、传播范围广等特点。随着互联网的普及&#xff0c;越来越多的企业和个人开始关注和投入电子杂志的制作。然而&#xff0c;电子杂志的制作过程往往复杂繁琐&#xff0c;需要付出大量的时间和精力。为了提高…

微信小程序学习(六):常用原生 API

&#x1f517;API官方文档 1、网络请求 wx.request({// 接口地址&#xff0c;仅为示例&#xff0c;并非真实的接口地址url: example.php,// 请求的参数data: { x: },// 请求方式 GET|POST|PUT|DELETEmethod: GET,success (res) {console.log(res.data)},fail(err) {console.…

本地离线模型搭建指南-本地运行显卡选择

搭建一个本地中文大语言模型&#xff08;LLM&#xff09;涉及多个关键步骤&#xff0c;从选择模型底座&#xff0c;到运行机器和框架&#xff0c;再到具体的架构实现和训练方式。以下是一个详细的指南&#xff0c;帮助你从零开始构建和运行一个中文大语言模型。 本地离线模型搭…

05 - matlab m_map地学绘图工具基础函数 - 设置比例尺指北针

05 - matlab m_map地学绘图工具基础函数 - 设置比例尺指北针 0. 引言1. 关于m_scale2. 关于m_ruler3. 关于m_northarrow4. 结语 0. 引言 本篇介绍下m_map中添加指北针(m_northarrow)、比例尺(m_ruler)和进行比例缩放(m_scale)的函数及其用法 。 1. 关于m_scale m_scale用于图件…

LeetCode 算法:二叉树的中序遍历 c++

原题链接&#x1f517;&#xff1a;二叉树的中序遍历 难度&#xff1a;简单⭐️ 题目 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&…

【Pandas驯化-14】一文搞懂Pandas中的时间处理函数date_range、resample、shift技巧

【Pandas驯化-14】一文搞懂Pandas中的时间处理函数date_range、resample、shift技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 相关…

PHP米表域名出售管理源码带后台

源码介绍 html5米表源码PHP域名销售程序安装方法&#xff1a; 本站已测试,各项功能正常,功能易用,不复杂,非常适合个人米表使用 1、所有文件传至网站目录 2、浏览器执行http://你的访问网址/install 3、输入mysql帐号及密码信息&#xff0c;提交安装 源码截图 源码下载 …

华为od-C卷200分题目3 - 两个字符串间的最短路径问题

华为od-C卷200分题目3 - 两个字符串间的最短路径问题 题目描述 给定两个字符串&#xff0c;分别为字符串A与字符串B。 例如A字符串为ABCABBA&#xff0c;B字符串为CBABAC可以得到下图m*n的二维数组&#xff0c;定义原点为(0, 0)&#xff0c;终点为(m, n)&#xff0c;水平与垂…

【Android逆向】小白也能学会的一个小时破解某猫社区VIP会员

第二步&#xff1a;使用 dex2jar 将 classes.dex 转成 jar 文件 cmd到dex2jar文件夹目录&#xff0c;执行 d2j-dex2jar D://xxx/xxx/classes.dex 得到 jar 文件 静态分析 拿到源码后&#xff0c;首先我们需要找到应用的限制点&#xff0c;绕过App里面的判断。 然后分析源码&…

520. 检测大写字母

题目 我们定义&#xff0c;在以下情况时&#xff0c;单词的大写用法是正确的&#xff1a; 全部字母都是大写&#xff0c;比如 “USA” 。单词中所有字母都不是大写&#xff0c;比如 “leetcode” 。如果单词不只含有一个字母&#xff0c;只有首字母大写&#xff0c;比如 “Go…

React学习(二)——状态(数据)与状态修改

useState 在React中&#xff0c;useState 是一个非常重要的Hook&#xff0c;它允许你在函数组件中添加“状态”&#xff08;state&#xff09;。在传统的React类组件中&#xff0c;我们使用this.state来管理和更新组件的状态。然而&#xff0c;在函数组件中&#xff0c;由于它们…

【Docker】Docker下载安装_使用阿里云加速配置

1、下载安装 1.1前提条件 安装环境&#xff1a; 目前&#xff0c;CentOS 仅发行版本中的内核支持 Docker。Docker 运行在 CentOS 7 上&#xff0c;要求系统为64位、系统内核版本为 3.10 以上。Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上&#xff0c;要求系统为64位…