「C++系列」数组

文章目录

  • 一、数组
    • 1. 声明数组
    • 2. 初始化数组
    • 3. 访问数组元素
    • 4. 遍历数组
    • 注意事项
    • 示例代码
  • 二、多维数组
    • 1. 声明二维数组
    • 2. 初始化二维数组
    • 3. 访问二维数组元素
    • 4. 遍历二维数组
    • 注意事项
    • 示例代码
  • 三、指向数组的指针
    • 1. 声明指向数组的指针
    • 2. 通过指针访问数组元素
    • 3. 指针和数组的关系
    • 4. 使用指向数组的指针进行排序
  • 四、传递数组给函数
    • 方法1:传递数组名和大小
    • 方法2:使用引用传递数组(不推荐用于原始数组)
    • 方法3:使用模板和引用传递(对于固定大小的数组)
    • 注意事项
  • 五、从函数返回数组
    • 方法1:返回指向静态数组的指针
    • 方法2:使用 `std::array` 或 `std::vector`
      • 使用 `std::array`
      • 使用 `std::vector`
    • 方法3:返回指向动态分配数组的指针(需要手动管理内存)
  • 六、相关链接

一、数组

C++ 中的数组是一种基础的数据结构,用于存储相同类型的数据的集合。数组中的每个元素可以通过索引(或下标)来访问,索引通常是从 0 开始的。数组的大小在声明时必须指定,并且之后不能改变(尽管可以通过一些技巧如动态内存分配来模拟可变大小的数组,但这通常涉及到指针和动态内存管理)。
在这里插入图片描述

1. 声明数组

数组的声明需要指定数组的类型和大小。例如,声明一个整型数组 arr,包含 5 个元素:

int arr[5];

2. 初始化数组

在声明数组的同时,可以初始化数组中的元素。例如:

int arr[5] = {1, 2, 3, 4, 5};

如果初始化时提供的元素少于数组的大小,则未明确初始化的元素将被自动初始化为零(对于内置类型如 intfloat 等)。

3. 访问数组元素

使用索引来访问数组中的元素。索引是从 0 开始的。例如,访问上面声明的数组 arr 的第一个元素:

int firstElement = arr[0]; // firstElement 的值为 1

4. 遍历数组

遍历数组通常使用循环结构,如 for 循环。例如,打印数组 arr 的所有元素:

for (int i = 0; i < 5; i++) {std::cout << arr[i] << " ";
}
std::cout << std::endl;

注意事项

  • 数组的大小在编译时确定,之后不能改变。
  • 数组越界是未定义行为,可能导致程序崩溃或数据损坏。因此,访问数组元素时要确保索引在有效范围内。
  • C++ 标准库提供了 std::vector 容器,它是一个更灵活、更安全的数组替代品,能够动态地增长和缩小。

示例代码

下面是一个完整的示例,展示了如何声明、初始化、访问和遍历数组:

#include <iostream>int main() {int arr[5] = {1, 2, 3, 4, 5};// 访问数组的第一个元素std::cout << "第一个元素是: " << arr[0] << std::endl;// 遍历数组并打印所有元素for (int i = 0; i < 5; i++) {std::cout << arr[i] << " ";}std::cout << std::endl;return 0;
}

输出将是:

第一个元素是: 1
1 2 3 4 5 

二、多维数组

C++ 中的多维数组是数组的数组,用于存储具有两个或更多维度的数据。最常见的是二维数组,但它可以扩展到更高维度。多维数组中的每个元素都可以通过一组索引来访问,这些索引对应于数组的每个维度。

1. 声明二维数组

二维数组可以看作是数组的数组,其中每个内部数组(或行)具有相同数量的元素。以下是声明二维数组的语法:

type arrayName[rows][columns];

其中 type 是数组元素的类型,arrayName 是数组的名称,rows 是数组的行数,columns 是数组的列数。

2. 初始化二维数组

在声明二维数组时,可以立即初始化它。如果初始化时省略了某些元素,则这些元素将被自动初始化为零(对于内置类型)。

int matrix[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}
};

如果初始化时只提供了部分行,则剩余的行将被自动初始化为零。

3. 访问二维数组元素

二维数组中的元素通过两个索引来访问:第一个索引指定行,第二个索引指定列。

int secondRowThirdColumn = matrix[1][2]; // 值为 7

4. 遍历二维数组

遍历二维数组通常涉及嵌套循环,外层循环遍历行,内层循环遍历列。

for (int i = 0; i < 3; i++) {for (int j = 0; j < 4; j++) {std::cout << matrix[i][j] << " ";}std::cout << std::endl;
}

注意事项

  • 多维数组的大小在编译时确定,之后不能改变。
  • 访问数组元素时要确保索引在有效范围内,以避免数组越界。
  • C++ 标准库中的 std::vector<std::vector<T>> 可以作为二维数组的替代品,提供更大的灵活性和动态内存管理。

示例代码

以下是一个完整的示例,展示了如何声明、初始化、访问和遍历二维数组:

#include <iostream>int main() {int matrix[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};// 访问并打印第二行第三列的元素std::cout << "第二行第三列的元素是: " << matrix[1][2] << std::endl;// 遍历并打印整个二维数组for (int i = 0; i < 3; i++) {for (int j = 0; j < 4; j++) {std::cout << matrix[i][j] << " ";}std::cout << std::endl;}return 0;
}

输出将是:

第二行第三列的元素是: 7
1 2 3 4 
5 6 7 8 
9 10 11 12 

三、指向数组的指针

在C++中,指向数组的指针是一个特殊的指针,它指向数组的第一个元素的地址。通过这个指针,我们可以访问和修改数组中的元素。然而,需要注意的是,指针本身并不知道它所指向的数组的大小,这意味着在通过指针遍历数组时,我们需要知道何时停止,以避免越界访问。

1. 声明指向数组的指针

当我们声明一个指向数组的指针时,我们通常会让它指向数组的第一个元素。指针的类型应该与数组元素的类型相匹配。

int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr; // ptr 指向 arr 的第一个元素

在这里,ptr 是一个指向 int 的指针,它被初始化为指向 arr 数组的第一个元素。由于数组名(在这里是 arr)在大多数表达式中会被解释为指向其第一个元素的指针,所以上面的 ptr = arr; 是合法的。

2. 通过指针访问数组元素

一旦我们有了指向数组第一个元素的指针,我们就可以使用指针算术来访问数组中的其他元素。

#include <iostream>int main() {int arr[5] = {1, 2, 3, 4, 5};int* ptr = arr;// 使用指针访问数组元素for (int i = 0; i < 5; i++) {std::cout << *(ptr + i) << " "; // 等同于 arr[i]}std::cout << std::endl;return 0;
}

3. 指针和数组的关系

在C++中,数组名在很多情况下会被隐式地转换为指向其第一个元素的指针。但是,有几个重要的区别:

  1. 大小信息丢失:当数组名被用作指针时,它不再携带关于数组大小的信息。因此,通过指针遍历数组时,我们需要知道数组的大小。
  2. 类型不同:尽管在大多数上下文中数组名可以像指针一样使用,但它们的类型是不同的。数组名是一个常量指针,指向数组的第一个元素,并且它的类型是“N个T类型的数组”,其中N是数组的大小,T是元素的类型。而指针是一个指向T类型对象的变量。
  3. 使用 sizeof 操作符:对数组使用 sizeof 会返回整个数组的大小(以字节为单位),而对指针使用 sizeof 会返回指针本身的大小(这取决于平台和编译器)。

4. 使用指向数组的指针进行排序

下面是一个简单的示例,展示了如何使用指向数组的指针来对数组进行排序(这里使用冒泡排序作为示例)。

#include <iostream>void bubbleSort(int* arr, int n) {for (int i = 0; i < n-1; i++) {for (int j = 0; j < n-i-1; j++) {if (*(arr + j) > *(arr + j + 1)) {// 交换 arr[j] 和 arr[j+1]int temp = *(arr + j);*(arr + j) = *(arr + j + 1);*(arr + j + 1) = temp;}}}
}int main() {int arr[5] = {5, 3, 8, 4, 2};int n = sizeof(arr)/sizeof(arr[0]);bubbleSort(arr, n);for (int i = 0; i < n; i++) {std::cout << arr[i] << " ";}std::cout << std::endl;return 0;
}

四、传递数组给函数

在C++中,传递数组给函数通常是通过传递数组的指针来完成的。由于数组名在大多数情况下会被解释为指向其第一个元素的指针,因此你可以直接将数组名作为参数传递给函数。然而,这种方式并不会传递数组的大小,所以通常还需要将数组的大小作为另一个参数传递给函数。

方法1:传递数组名和大小

这是最常见的方法,你将数组名(实际上是指向数组第一个元素的指针)和数组的大小作为两个独立的参数传递给函数。

#include <iostream>// 函数声明,接收指向int的指针和数组的大小
void printArray(int* arr, int size) {for (int i = 0; i < size; i++) {std::cout << arr[i] << " ";}std::cout << std::endl;
}int main() {int myArray[5] = {1, 2, 3, 4, 5};// 传递数组名和大小给函数printArray(myArray, 5);return 0;
}

方法2:使用引用传递数组(不推荐用于原始数组)

需要注意的是,在C++中你不能直接传递数组的引用(如 void func(int (&arr)[5]); 这样的声明在函数模板之外是不允许的,因为它要求数组的大小在编译时已知)。然而,你可以通过传递指向数组的指针来模拟这种行为,或者如果你在处理的是固定大小的数组,并且希望避免传递大小参数,你可以考虑使用模板(但这不是传递数组的“引用”,而是类型推导)。

方法3:使用模板和引用传递(对于固定大小的数组)

虽然这不是直接传递数组给函数的标准方式,但如果你在处理固定大小的数组,并且想要避免传递大小参数,你可以使用模板。

#include <iostream>// 模板函数,用于处理固定大小的数组
template<size_t N>
void printFixedArray(int (&arr)[N]) {for (size_t i = 0; i < N; i++) {std::cout << arr[i] << " ";}std::cout << std::endl;
}int main() {int myArray[5] = {1, 2, 3, 4, 5};// 使用模板函数,不需要传递大小printFixedArray(myArray);return 0;
}

注意事项

  • 当通过指针传递数组时,请确保在函数内部不会越界访问数组。
  • 传递数组时,并不会复制数组本身,而是传递了指向数组第一个元素的指针。因此,函数内部对数组元素的修改将影响原始数组。
  • 如果你正在处理动态分配的数组(例如,使用 new 关键字分配的数组),请确保在不再需要时释放内存(使用 delete[])。然而,在传递动态分配的数组给函数时,你通常只需要传递指向数组的指针,而不需要传递数组的大小(如果函数内部有逻辑来确定大小的话),但最佳实践是始终传递大小以避免潜在的错误。

五、从函数返回数组

在C++中,直接从函数返回一个数组本身是不被直接支持的,因为数组名在表达式中通常会被视为指向其第一个元素的指针,而不是一个可以返回的对象。但是,有几种方法可以模拟从函数返回数组的行为。

方法1:返回指向静态数组的指针

这种方法涉及在函数内部定义一个静态数组,并返回指向该数组的指针。然而,这种方法有局限性,因为它返回的总是同一个数组的引用,可能在多线程环境下导致问题,并且数组的大小在编译时就已确定。

#include <iostream>int* returnArray() {static int arr[] = {1, 2, 3, 4, 5};return arr;
}int main() {int* myArray = returnArray();for (int i = 0; i < 5; i++) {std::cout << myArray[i] << " ";}std::cout << std::endl;return 0;
}

方法2:使用 std::arraystd::vector

std::array 是一个固定大小的数组容器,而 std::vector 是一个可变大小的数组容器。它们都提供了复制和移动语义,因此可以直接从函数返回。

使用 std::array

#include <iostream>
#include <array>std::array<int, 5> returnArray() {return {1, 2, 3, 4, 5};
}int main() {std::array<int, 5> myArray = returnArray();for (int i : myArray) {std::cout << i << " ";}std::cout << std::endl;return 0;
}

使用 std::vector

#include <iostream>
#include <vector>std::vector<int> returnArray() {return {1, 2, 3, 4, 5};
}int main() {std::vector<int> myArray = returnArray();for (int i : myArray) {std::cout << i << " ";}std::cout << std::endl;return 0;
}

方法3:返回指向动态分配数组的指针(需要手动管理内存)

这种方法涉及在堆上动态分配数组,并返回指向该数组的指针。调用者需要负责在不再需要时释放内存。

#include <iostream>int* returnArray(int size) {int* arr = new int[size];for (int i = 0; i < size; i++) {arr[i] = i + 1;}return arr;
}int main() {int* myArray = returnArray(5);for (int i = 0; i < 5; i++) {std::cout << myArray[i] << " ";}std::cout << std::endl;delete[] myArray; // 不要忘记释放内存return 0;
}

在这里插入图片描述

六、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C++系列」C++简介、应用领域
  4. 「C++系列」C++ 基本语法
  5. 「C++系列」C++ 数据类型
  6. 「C++系列」C++ 变量类型
  7. 「C++系列」C++ 变量作用域
  8. 「C++系列」C++ 常量知识点-细致讲解
  9. 「C++系列」C++ 修饰符类型
  10. 「C++系列」一篇文章说透【存储类】
  11. 「C++系列」一篇文章讲透【运算符】
  12. 「C++系列」循环
  13. 「C++系列」判断
  14. 「C++系列」函数/内置函数
  15. 「C++系列」数字/随机数

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

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

相关文章

Android 10.0 framework默认沉浸式状态栏功能实现

1. 前言 在10.0的系统rom定制化开发中,在实现状态栏的某些定制化开发中,在某些产品需要实现沉浸式状态栏,就是需要app 能全屏显示同样也能显示状态栏,接下来就来分析下相关的功能实现 如图: 2.framework默认沉浸式状态栏功能实现的核心类 frameworks\base\core\java\andro…

【神经网络】梯度下降的优化方法【数学公式+代码示例】

文章目录 1、简介2、指数加权平均2.1、公式2.2、代码 3、Momentum⭐3.1、公式演变3.2、代码 4、AdaGrad4.1、计算步骤4.2、代码示例 5、RMSProp5.1、公式5.2、代码5.3、小结 6、Adam6.1、公式和步骤解释⭐6.2、代码⭐6.3、优点 7、何为鞍点8、小结 &#x1f343;作者介绍&#…

国防科技大学深圳地区新生欢送会圆满举行

2024年7月28日&#xff0c;第97个八一建军节来临之际&#xff0c;在这个充满希望的盛夏时节&#xff0c;深圳地区迎来了13名即将踏入国防科技大学的优秀学子。 为了庆祝这一荣耀时刻&#xff0c;并表达对新生的深切祝福&#xff0c;在国防科技大学深圳校友会黄丹会长的积极倡议…

书生大模型实战营--L1关卡-Llamaindex RAG实践

一、安装llamaindex库 pip install llama-index pip install llama-index-embeddings-huggingface 二、问2024年巴黎奥运会 中国队获得几枚金牌&#xff0c;无法回答该问题 三、构建Llamaindex RAG 1、初始化llm 2、构建词向量模型 下载模型&#xff1a;git clone https://…

基于k8s快速搭建docker镜像服务的demo

基于k8s快速搭建docker镜像服务的demo 一、环境准备 如标题&#xff0c;你需要环境中有和2个平台&#xff0c;并且服务器上也已经安装好docker服务 接下来我来构建一个docker镜像&#xff0c;然后使用harbork8s来快速部署服务demo 二、部署概述 使用docker构建镜像&#x…

(2024,通用逼近定理(UAT),函数逼近,Kolmogorov–Arnold定理(KAT),任意深度/宽度的网络逼近)综述

A Survey on Universal Approximation Theorems 公和众与号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 2. 神经网络&#xff08;NN&#xff09; 3. 通用逼近定理&#xff0…

我的NAS是怎么连接Amazon Web Services S3的

作为IT爱好者&#xff0c;很多家庭都配备了Network Attached Storage&#xff08;NAS&#xff09;&#xff0c;用于存储和管理大量数据。一个常见的挑战是如何实现异地备份&#xff0c;以确保数据的安全性和可恢复性。以下是一些解决方案和工具&#xff0c;可以帮助用户有效地管…

“手撕”MySQL的索引

目录 二、索引的作用 三、索引的缺点 四、如何使用索引 查看索引&#xff1a; 创建索引&#xff1a; ​编辑 删除索引&#xff1a; 五、索引的底层原理 那什么是B树&#xff0c;什么是B树呢&#xff1f; B树的好处&#xff1a; 总结&#xff1a; 一、什么是索引 索…

C语言的周末小练习(贰)

周末小练习&#xff1a; 5、输入身高和体重&#xff0c;计算BMI指数(BMI w/(h*h))。 #include <stdio.h>int main() {float w,h,BMI;/*printf("请输入体重\n");scanf("%f",&w);printf("请输入身高\n");scanf("%f",&h…

vue3 快速入门 (五) : Flex布局

1. 如何变成Flex布局 变成Flex容器&#xff0c;只需在容器布局的节点的CSS中&#xff0c;增加display : flex .mylayout {/* 省略了其他代码 */display: flex; }2. flex direction : 方向 row : 以行排列 row-reverse &#xff1a; 以行反向排列 column &#xff1a;以列排列…

Matlab编程资源库(11)多项式计算

一、多项式的四则运算 1&#xff0e;多项式的加减运算 2&#xff0e;多项式乘法运算 函数conv(P1,P2)用于求多项式P1和P2的乘积。 这里&#xff0c;P1、P2是两个多项式系数向量。 3&#xff0e;多项式除法 函数[Q,r]deconv(P1,P2)用于对多项式P1和P2作除法运算。其中Q返回多项…

【前端 09】JavaScript中的对象与JSON

JavaScript中的对象与JSON 在JavaScript中&#xff0c;对象和JSON&#xff08;JavaScript Object Notation&#xff09;是两个紧密相连但又有区别的概念。它们都在数据处理和交换中扮演着重要角色。本文将详细讲解JavaScript中的自定义对象以及JSON对象的基本概念、格式、用法…

基于微信小程序+SpringBoot+Vue的教务管理系统(带1w+文档)

基于微信小程序SpringBootVue的教务管理系统(带1w文档) 基于微信小程序SpringBootVue的教务管理系统(带1w文档) 在目前的情况下&#xff0c;可以引进一款基于web的高校教务管理系统这样的现代化管理工具&#xff0c;这个工具就是解决上述问题的最好的解决方案。它不仅可以实时完…

python拼接字符串方法

文章目录 1. 使用加号&#xff08;&#xff09;2. 使用str.join()方法3. 使用格式化字符串&#xff08;f-strings, % 操作符, .format() 方法&#xff09;4. 使用列表推导式和join()结合 性能对比 在Python中&#xff0c;字符串拼接是将两个或多个字符串合并成一个新字符串的过…

生成RSA公钥的n值

简介&#xff1a;RSA算法是一种非对称加密算法&#xff0c;与对称加密算法不同的是,RSA算法有两个不同的密钥,一个是公钥,一个是私钥。 原理是&#xff1a;根据数论&#xff0c;寻求两个大素数比较简单&#xff0c;而将它们的乘积进行因式分解却极其困难&#xff0c;因此可以将…

【leetcode 详解】生成特殊数字的最少操作【中等】(C++思路精析)

题目见下&#xff1a; 测试数据: 解题思路笔记&#xff1a; 最初拿到这道题是很蒙的&#xff0c;联想不到什么数据结构的模型&#xff08;肯定是笔者积累太少了&#xff09;&#xff0c;甚至惯性地想怎么实现“删除数字”的操作&#xff1a;在原字符串中抽出一个字符然后将剩…

VS code 与Pycharm 的使用区别(个人)

注明&#xff1a;本文从这开始VS code简称VS&#xff0c;Pycharm简称PY 安装包大小 VS:PY 1:0 安装后实际大小 vs py VS:PY 2:0 界面ui&#xff08;简易&#xff09; vs py VS:PY 2:1 启动速度 VS:PY 3:1 注&#xff1a;以上为个人测评&#xff0c;无特殊意图

为什么AI会一本正经地胡说八道

泛泛地说&#xff0c;AI一本正经地胡说八道的原因可以归结为&#xff1a;AI的理解能力受到其训练数据和算法的限制&#xff0c;如果问题表达不清晰或者背景信息不足&#xff0c;AI可能会产生错误的推理或输出&#xff1b;AI语言模型本质上是基于统计学习和模式匹配的&#xff0…

第一个设计模式——单例模式

目录 一、特点&#xff1a; 二、实现单例模式步骤 三、饿汉式 四、懒汉式 五、双重检查锁 六、静态内部类 七、枚举 八、可能被反序列化和反射破坏什么意思&#xff1f; 九、如何解决呢&#xff1f; 一、特点&#xff1a; 唯一性&#xff0c;单例模式确保程序中只有一…

数据结构 -- 算法的时间复杂度和空间复杂度

数据结构 -- 算法的时间复杂度和空间复杂度 1.算法效率1.1 如何衡量一个算法的好坏1.2 算法的复杂度 2.时间复杂度2.1 时间复杂度的概念2.2 大O的渐进表示法2.3常见时间复杂度计算举例 3.空间复杂度4. 常见复杂度对比 1.算法效率 1.1 如何衡量一个算法的好坏 如何衡量一个算法…