C++复合类型

2023-11-09

1、数组

数组声明应该指出元素类型、数组名和元素个数。数组的初始化需要遵循以下规则:

a. 只有定义数组时才能使用初始化,此后就不能使用了,也不能将一个数组赋给另一个数组

	int narray1[4] = { 1, 2, 3, 4 };
	int narray2[4];
	// narray2 = { 2, 3, 4, 5 };	// not allowed
	// narray2 = narray1;			// not allowed

初始化结束后只能通过下标来给数组元素赋值

b. 初始化数组时,提供的值可以少于数组的元素数目

int narray1[4] = { 1, 2};

c. 初始化数组时没有指定元素个数,C++编译器将计算元素的个数,我们可以通过sizeof来计算元素个数

	int arr[] = { 1, 2, 3, 4};
	cout << sizeof(narray1) / sizeof(narray1[1]);

数组的初始化方法:

列表初始化(花括号初始化)作为通用初始化方式,适用于任何类型,当然也支持数组初始化。

	int arr1[3] = { 1, 2, 3 };
	int arr2[]{ 1, 2, 3, 4 };
	int arr3[10]{};

花括号里不填任何东西时,所有元素将被设置为0。

2、字符串

字符串是存储在连续内存中的一串字符。C++处理字符串的方式有两种:C风格字符串 和 基于string类的字符串。

a. C风格字符串

C风格字符串以空字符'\0'结尾,ASCII值为0:

	char str1[] = { 'h', 'e', 'l', 'l', 'o' };		// not a string
	char str2[] = { 'h', 'e', 'l', 'l', 'o', '\0'};	// string

除了用数组来初始化字符串,还有一种双引号括号的字符串,这种字符串被称为字符串常量:

    char str1[] = "this is a const string";
	str1[0] = 'a';
	cout << str1;        // ahis is a const string

我们可以用数组下标来修改字符串的内容。

任何两个有空白(空格、制表符、换行符)分隔的字符串常量可以拼接为一个,拼接后的字符串之间不会添加空格,前一个字符串的'\0'会被后一个字串取代

	cout << "hello " "world " "!!!!" << endl;	// hello world !!!!
	cout << "hello "
		"world "
		"!!!!" << endl;							// hello world !!!!

    #define HEL "hello"
    cout << HEL" world";	                    // hello world

	char str[] = "hello " "world"
					"!!!";
	cout << str;	                            // hello world!!!

b. string类简介

string类位于命名空间std中,可以通过using std::string来引入,string类隐藏了字符串的数组性质。string可以有以下初始化方式:

	string str1 = "hello world";
	string str2 = { "hello world" };
	string str3("hello world");
	string str4{ "hello world" };
	string str5 = str1;
	string str6(str1);

3、结构体简介

结构体是一种比数组更为灵活的数据格式,同一个结构可以存储多种类型的数据。结构体可以有外部声明(可以被其后面的任何函数使用)和内部声明(被该声明所属的函数使用)。

C++11结构创建与初始化:

	struct student
	{
		char name[20];
		int age;
		bool gender;
	};
 
	student s1 = { "ming", 11, true };
	student s2{ "hong", 10, false };
    student s3{};  // 初始化为0
    
    student s4;    // 这时候结构体中的成员都是未初始化的,使用可能会出现未知的问题
    memset(&s4, 0, sizeof(s4));

    // 指定初始化,不是所有的编译器都支持的,linux中常用
    student s5 = { .name = "bing", .age = 10, .gender = false };

结构体定义和创建结构体变量可以同时完成,初始化也可以同时完成:

	struct student
	{
		char name[20];
		int age;
		bool gender;
	} s1 = {}, s2 =
	{
		"ming", 11, true
	};

我们还可以声明匿名的结构体类型,但是我们必须要在定义的同时声明变量:

	struct 
	{
		int x;
		int y;
	} position;

有了结构体我们可以声明结构体数组了:

	student ss[3]{
		{ "ming", 11, true },
		{ "hong", 10, false },
		{ }
	}

结构体中的位字段:与C语言一样,C++也允许指定占用特定位数的结构成员,使得创建与某个硬件设备上的寄存器对应的数据结构非常方便。字段的类型应为整形或者枚举,接下来是冒号,冒号后面是一个数字,指定了使用的位数。可以使用没有名称的字段提供间距。每个成员都被称为位字段。

	struct torgle_register
	{
		unsigned int a : 4;		// 4 bits for SN
		unsigned int : 4;		// 4 bits unused
		unsigned int b : 2;		// 2 bits unused
		unsigned int c : 14;	// 14 bits unused
	} tr;
	tr = { 0xf, 0x3, 0xfff };
	cout << hex;
	cout << tr.a << " " << tr.b << " " << tr.c << endl;		// f 3 fff
	tr = { 0xf1, 0x5, 0x4fff };
	cout << tr.a << " " << tr.b << " " << tr.c << endl;		// 1 1 fff
	cout << "sizeof(tr) = " << sizeof(tr);					// 4

位段的存储规则:当相邻成员的类型相同时,如果它们的位宽之和小于类型的 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将从新的存储单元开始,其偏移量为类型大小的整数倍。计算位段结构体大小时可能还需要兼顾到内存对齐,这里暂不介绍。

4、共用体

共用体能够存储不同的数据类型,但是只能同时存储其中的一种类型。由于每次只能存储一个值,所以必须要有足够的空间来存储最大的成员,共用体的长度为其最大成员的长度。

	struct widget {
		char brand[20];
		int type;
		union id {
			long id_num;
			char id_char[20];
		} id_val;
	};

    cout << sizeof(widget);    // 44

	w1.id_val.id_num = 10;
	w1.id_val.id_char[0] = 20;
	cout << w1.id_val.id_num;	// 20

匿名共用体的成员会被是为结构体成员的两个成员,我们使用时需要先确定哪个成员是正在活动的:

	struct widget2 {
		char brand[20];
		int type;
		union{
			long id_num;
			char id_char[20];
		};
	} w1 = {};
	if (w1.type == 1)
		w1.id_num = 10;
	else
		memcpy(w1.id_char, "apple", strlen("apple"));

5、枚举

C++的enum提供了另一种创建符号常量的方式,这种方式可以替代const。

默认情况下,将整数值赋给枚举量,第一个枚举量的值为0,第二个枚举量的值为1,以此类推;此外,我们可以通过显式指定整数值来覆盖默认值,我们也可以创建多个值相同的枚举量。

    enum MyEnum
	{
		APPLE,
		ORANGE,
		BANANA,
	};

枚举变量有些特殊的属性:在不进行强制转换的情况下,只能将定义枚举时使用的枚举量赋给这种枚举的变量。枚举量是整形,可被提升为int类型,但是int类型不能自动转换为枚举类型。

    MyEnum fruit;
	fruit = APPLE;
	// fruit = 1000;        // invalid
	fruit = MyEnum(2);
    // fruit = 1 + APPLE;   // invalid
    // fruit = 2;           // invalid
    int nu = 1 + APPLE;     // valid

枚举的上限为大于最大值的、最小的2的幂减1,最小值如果大于等于0则下限为0,否则下限的计算方式和上限相同。下例中6不是枚举值,但是它位于枚举定义的取值范围内。

	enum bits {
		one = 1,
		two = 2,
		four = 4,
		eight = 8,
	};
	bits myflag = bits(6);
    // bits myflags2 = bits(9); // invalid

6、指针和自由存储空间

指针是一个变量,存储的是一个值的地址,而不是值本身。指针声明必须指定指针指向的数据的类型。以下声明的是一个指针变量和一个int变量:

	int * p, p1;

我们可以通过new 和 delete来分配、释放内存

	int * p = new int;
	*p = 100;
	delete p;
	p = NULL;

也可以通过malloc 和 free来分配、释放内存

	int *p = (int*)malloc(sizeof(int));
	*p = 100;
	cout << p << " " << *p << endl;        // 00DE89B8 100
	free(p);
	p = NULL;

使用new来创建动态数组:

	int *p = new int[10];
	// int p[10] = new int[10];		// invalid
    delete[] p;

7、指针、数组和指针算数

指针变量加1,其增加的值等于指向的类型占用的字节数。

很多情况下我们可以以相同的方式使用指针名和数组名,包括方括号表示法和解引用运算符。区别是指针的值可以被修改,而数组名是常量;另一个区别是对数组应用sizeof运算符得到的是数组的长度,对指针应用sizeof得到的是指针的长度。

	int array[10]{};
	int *parray = new int[10];
	array[2] = 2;
	*(array + 3) = 3;
	parray[2] = 2;
	*(parray + 3) = 3;
	parray++;
	// array = array + 1; not allowed
	cout << sizeof(array) << endl;	// 40
	cout << sizeof(parray) << endl;	// 4

    int *p = array;

数组名会被解释为其第一个元素的地址,对数组名应用地址运算符时,得到的是整个数组的地址

	short tell[3]{};
	cout << &tell[0] << endl;      // 012FFB64
	cout << tell << endl;          // 012FFB64
	cout << &tell << endl;         // 012FFB64
	cout << tell + 1 << endl;      // 012FFB66     + 2
	cout << &tell + 1 << endl;     // 012FFB6A     + 6

数组指针:指向数组的指针

变量首先和*结合说明是一个指针,指向的类型是 short []

	short (*pas)[3] = &tell;

指针数组:存储指针的数组

变量首先和[]结合说明是一个数组,存储的类型是short *

	short *pp[3]{};

指向同一个数组的指针相减得到的是两个元素之间的间隔

	short *p1 = tell;
	short *p2 = &tell[2];
	cout << p2 - p1 << endl;    // 2
	cout << p1 - p2 << endl;    // -2

8、自动存储、静态存储和动态存储

自动存储:函数内部定义的常规变量使用自动存储空间被称为自动变量,自动变量是一个局部变量,其作用域为包含它的代码块。

	{
		int a = 0;
	}

静态存储:整个程序执行期间都存在的存储方式,变量成为静态的方式有两种:一种是在函数外面定义它,另一种是在声明变量时使用关键字static。

// 函数外部明静态变量

static int ga = 0;

int addA()
{
	ga++;
	return ga;
}

int a = addA();
cout << a << endl;	// 1
a = addA();
cout << a << endl;	// 2
// 函数内声明静态变量
int addA()
{
	static int a = 0;
	a++;
	return a;
}

int a = addA();
cout << a << endl;	// 1
addA();
cout << a << endl;	// 2

以上两种声明方式的不同点在于:在函数内部声明的静态变量只能在函数内部访问到,而外部声明在声明位置之后都可以访问到。

动态存储:new和delete运算符提供了一种更灵活的方法,他们管理了一个内存池(heap),数据的生命周期不完全受程序或函数的生存时间控制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++复合类型 的相关文章

  • 如何在MVVM中管理多个窗口

    我知道有几个与此类似的问题 但我还没有找到明确的答案 我正在尝试深入研究 MVVM 并尽可能保持纯粹 但不确定如何在坚持模式的同时启动 关闭窗口 我最初的想法是向 ViewModel 发送数据绑定命令 触发代码来启动一个新视图 然后通过 X
  • 检查两个数是否是彼此的排列?

    给定两个数字 a b 使得 1 例如 123 是 312 的有效排列 我也不想对数字中的数字进行排序 如果您指的是数字的字符 例如 1927 和 9721 则 至少 有几种方法 如果允许排序 一种方法是简单地sprintf将它们放入两个缓冲
  • 如何使 Windows 窗体的关闭按钮不关闭窗体但使其不可见?

    该表单有一个 NotifyIcon 对象 当用户单击 关闭 按钮时 我希望表单不关闭而是变得不可见 然后 如果用户想再次查看该表单 可以双击系统托盘中的图标 如果用户想关闭表单 可以右键单击该图标并选择 关闭 有人可以告诉我如何使关闭按钮不
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • C#:如何防止主窗体过早显示

    在我的 main 方法中 我像往常一样启动主窗体 Application EnableVisualStyles Application SetCompatibleTextRenderingDefault false Application
  • 将目录压缩为单个文件的方法有哪些

    不知道怎么问 所以我会解释一下情况 我需要存储一些压缩文件 最初的想法是创建一个文件夹并存储所需数量的压缩文件 并创建一个文件来保存有关每个压缩文件的数据 但是 我不被允许创建许多文件 只能有一个 我决定创建一个压缩文件 其中包含有关进一步
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • 如何返回 json 结果并将 unicode 字符转义为 \u1234

    我正在实现一个返回 json 结果的方法 例如 public JsonResult MethodName Guid key var result ApiHelper GetData key Data is stored in db as v
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • clang 实例化后静态成员初始化

    这样的代码可以用 GCC 编译 但 clang 3 5 失败 include
  • C++ fmt 库,仅使用格式说明符格式化单个参数

    使用 C fmt 库 并给定一个裸格式说明符 有没有办法使用它来格式化单个参数 example std string str magic format 2f 1 23 current method template
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • mysql-connector-c++ - “get_driver_instance”不是“sql::mysql”的成员

    我是 C 的初学者 我认为学习的唯一方法就是接触一些代码 我正在尝试构建一个连接到 mysql 数据库的程序 我在 Linux 上使用 g 没有想法 我运行 make 这是我的错误 hello cpp 38 error get driver
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐

  • element table 中sortable排序

    在项目中做表格的排序 我使用的是自定义的排序 也就是通过后台接口进行的排序 写个文章记录一下element的三种排序方式 在列中设置sortable属性即可实现以该列为基准的排序 接受一个Boolean 默认为false 可以通过 Tabl
  • API接口整理收集常用Get-Post请求供测试使用

    百度 api集市免费接口 IP地址查询 http apistore baidu com apiworks servicedetail 114 html 频道新闻API 易源 http apistore baidu com apiworks
  • 【XML】学习笔记第四章-schema

    Schema 概述 作用 与DTD相比Schema的优势 基础命名空间 模式 引用方法 通过xsi noNamespaceSchemaLocation引入 通过xsi shemaLocation引入 Schema的语法结构 定义元素的主要语
  • shell脚本3个整数从小到大排序

    read p 请输入一个整数 num1 read p 请输入一个整数 num2 read p 请输入一个整数 num3 不管谁大谁小 最后打印 echo n u m 1 num1 num1 num2
  • Goby自定义漏洞之EXP

    前言 自定义漏洞配合EXP 提高漏洞的利用速度 简直是爽的飞起 自从HVV的时候Goby发布HVV专版 羡慕死了 就是太菜没傍上红方大佬的腿 虽然最终用上了HVV专版 但是一些只有你自己知道的漏洞 或者比较偏门的漏洞 就需要咱们自己来编写P
  • react小练习-antd Form表单和Table表格的交互-Table动态添加数据

    文章目录 功能实现效果 代码背景 代码思路 代码实现 功能实现效果 点击添加按钮 输入表单内容 表单提交后数据动态添加到Table表格里 如图 初始数据 是在dva的mock文件模拟的死数据 点击添加 输入数据 表单提交后 数据添加到表格里
  • Android签名概述

    一 Android签名概述 我们已经知道的是 Android对每一个Apk文件都会进行签名 在Apk文件安装时 系统会对其签名信息进行比对 判断程序的完整性 从而决定该Apk文件是否可以安装 在一定程度上达到安全的目的 给定一个Apk文件
  • JAVA实现蛇形矩阵算法

    JAVA实现蛇形矩阵算法 蛇形矩阵是一种特殊的二维矩阵 其元素按照一定的规律排列成蛇形 这种算法可以通过JAVA编程语言来实现 本文将介绍如何使用JAVA编写代码来生成蛇形矩阵 并给出相应的源代码 蛇形矩阵的生成规则如下 第一行从左到右依次
  • 多租户系统设计

    多租户系统设计 SaaS 的系统分级 SaaS 系统架构成熟度模型的 5 个级别 从 混乱 到 乌托邦 第 0 级 混乱 每次新增一个客户 都会新增软件的一个实例 第 1 级 受控的混乱 所有客户都运行在软件的同一个版本上 而且任何的定制化
  • 当在浏览器中输入一个域名后,会发生什么

    今天 去哪儿网Geely老师分享了他在校招时的一个面试题 当输www qunar com时发生了什么 真不是做广告哈 因为学的并没有很扎实 不能更深更广的分析这个问题 遂 百度一下 发现这篇文章并转载保存下来 同时也分享一下 希望大家可以更
  • vue-cli3.0打包时如何忽略某个第三方依赖包

    前几天接到了用vue重构某个业务模块的需求 常规开发不做讨论 但是在打包时需要排除业务中使用的某个第三方依赖包 代码如下 main js import Vue from vue import Cesium from cesium Cesiu
  • 解决Win7启动时出现“windows未能启动。原因可能是最近更改了硬件或软件”的问题

    搜索资料的时候发现个小问题 问题描述 在给ThinkPad T490做win7系统时 出现了 windows未能启动 原因可能是最近更改了硬件或软件 的问题 一直启动不来 在系统盘微PE中甚至还会出现 0x490 找不到元素 的问题 如何来
  • cuda安装笔记

    更新2023 3 4 我笔记本用vs编译后老是提示no kernel image is available for execution on the device 一直以为是驱动版本太高了或者cudatoolkit版本太高了 后来才知道是版
  • 【数据挖掘】知识点总结

    一 绪论 什么是数据挖掘 就是通过算法从大量的数据中搜索隐藏在其中的信息 数据挖掘的基本任务 聚类分析 异常检测 关联分析和预测建模 高维性和维灾难 随着维度的增加计算复杂度也随之增加 二 数据 不同的属性类型 标称 例如 邮政编码 定性数
  • 大数据应用——Linux常用的命令

    帮助命令 1 基本语法 help 命令 功能描述 获得shell内置命令的帮助信息 2 案例实操 1 查看cd命令的帮助信息 root hadoop01 help cd 常用快捷键 常用快捷键 功能 ctrl c 停止进程 ctrl l 清
  • Python(十五)读取Excel

    今天来实战演示如何封装读取Excel方法 第一步 准备一个Excel文件 sheet页命名为 login 学习技术交流群 704807680 第二步 编写代码找到Excel文件所在的文件夹路径 path os path dirname os
  • 机器学习算法——混淆矩阵(Confusion Matrix)之鸢尾花实例

    一 理论 什么是混淆矩阵 其实就是把所有类别的预测结果与真实结果按类别放置到了同一个表里 在这个表里我们可以清楚地看到每个类别正确识别的数量和错误识别的数量 混淆矩阵在什么情况下最好呢 答案是类别不平衡时 混淆矩阵是除了ROC曲线和AUC之
  • chatGPT高考作文

    百花齐放 春满人间 吹灭别人的灯 并不会让自己更加光明 阻挡别人的路 也不会让自己行得更远 这是一句古老而智慧的话语 告诉我们要尊重和包容他人 要与人和睦相处 要共同进步 同样的道理 也适用于文化的交流和发展 文化是一个民族的灵魂 是一个国
  • 华为OD机试真题-不爱施肥的小布

    题目描述 某农场主管理了一大片果园 fields i 表示不同果林的面积 单位 m 2 现在要为所有的果林施肥且必须在n天之内完成 否则影响收成 小布是果林的工作人员 他每次选择一片果林进行施肥 且一片果林施肥完后当天不再进行施肥作业 假设
  • C++复合类型

    1 数组 数组声明应该指出元素类型 数组名和元素个数 数组的初始化需要遵循以下规则 a 只有定义数组时才能使用初始化 此后就不能使用了 也不能将一个数组赋给另一个数组 int narray1 4 1 2 3 4 int narray2 4