C++数组的定义详情

作者:一个热爱学习的深度渣渣 时间:2023-07-21 08:00:49 

上一篇讲解了类型,通过类型来开始本篇的学习;


int a[10];

上述代码中的a是什么类型呢?

相信很多人都知道是一个数组类型,具体来说是一个int[10]的类型;

1.数组概念

定义:将一到多个相同对象串连到一起,所组成的类型;

初始化方式:

  • 缺省初始化int x[5];

  • 聚合初始化int x[] = {1,2,3};

注意:

  • 不能用auto来声明数组类型;

  • 数组不能复制,也不能赋值;

2.数组的复杂声明

指针数组的声明:


int *i[5];

大家思考下i的类型是什么?

指针数组表示数组内的每个元素都是int*类型,所以i的类型为int *[5];

数组指针的声明:


int (*x)[5];

大家思考下x的类型是什么?

这里a是一个指针,类型为int(*)[5];

3.数组到指针

  • 使用数组对象时,通常会产生数组到指针的隐式转换;

  • 可通过引用声明来避免隐式转换;


int a[3] = {1, 2, 3};
auto b = a;  // b的类型为int*
auto &b = a; // b的类型为int(&) [3]

数组和指针的转换关系图

C++数组的定义详情

指向数值开头的指针很好获得,比如a、&(a[0])、std::begin(a);

获取指向数组结尾的指针(上图指向80):a+3、&(a[3])、std::end(a);

使用标准库获取开头和结尾指针的方法在别的数据类型也适用;

4.数组操作

4.1获取数组元素个数


int x[3];
// 方法一
std::cout << sizeof(x) / sizeof(int) << std::endl;
// 方法二
std::cout << std::size(a) << std::endl;
// 方法三
std::cout << std::end(a) - std::begin(a) << std::endl;

方法三实际上是在运行期才执行的,增加程序运行耗时,不推荐;

方法一类型需要自己传入,适用性差,不推荐;

推荐用方法二;

4.2使用for循环遍历数组(C++11开始支持)


int a[3] = {1, 2, 3};
for (int x: a)
{
std::cout << x << std::endl;
}

5.拓展

5.1C字符串

  • C字符串本质也是数组;

  • 声明一个字符数组并打印长度


#include <cstring>
char a[] = "Hello";
std::cout << strlen(a) <<std::endl;

使用函数strlen需要引入头文件cstring

5.2vector

定义:是C++标准库中定义的类模板;

与内建数组相比,更侧重于易用性(相对而言性能比内建数组差),可复制,可在运行期动态改变元素个数;
初始化与构建


// 1、聚合初始化
std::vector<int> x = {1, 2, 3};
// 2、其他初始化方式
std::vector<int> x(3, 1); // 个数为3,并且每个元素都为1

vector的初始化方式还有很多,可参考:https://en.cppreference.com/w/cpp/container/vector/vector

获取元素个数


std::cout << x.size() << std::endl;

判断为空


std::cout << x.empty() << std::endl;

尾部添加元素


x.push_back(2);  // 向容器中添加一个整数2

删除最后一个元素


x.pop_back();

打印vector中的元素


std::vector<int> x = {1, 2, 3};
x[2];   // 跟数组一样,越界不报错
x.at(2);  // 不可以越界

在标准库中的beginend函数,在vector中也有同名的方法并且作用相同,返回一个迭代器;

可以使用指针引用一个vector对象的方法:


std::vector<int> x = {1, 2, 3};
std::vector<int>* p = &x;
std::cout << p->size() << std::endl;

5.3string

定义:是C++标准库中定义的一个类模板特化别名,用于内建字符串的替代品;

  • 与内建字符串相比,更侧重易用性,可复制,可在运行期动态改变字符串个数;

  • 构造和初始化,可参考:https://en.cppreference.com/w/cpp/string/basic_string

  • 支持比较、赋值、拼接、索引、转换为C字符串(c_str());

6.思考

6.1思考以下代码输出什么?


int i[3] = {1, 2, 3};
std::cout << *(a) << std::endl;   // 第一行
std::cout << *(a + 1) << std::endl;  // 第二行

第一行的输出是1,第二行输出的是2,这就相当于a[0]和a[1]的值,说明数组底层也是指针实现,第二行中加一表示首地址地址移动类型大小的字节;

6.2以下代码能够编译通过吗?


int a[2] = {1, 2};
std::cout << a[100] << std::endl;

这个数组越界在C++中是可以编译通过的,会输出一个毫无关系的值,编译器不会有边界检查,需要特别注意!

6.3在另一个文件中定义了数组,如何在该文件中定义?


test.cpp:

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

main.cpp:

extern int arr[];

上述声明称为不完整类型的声明,可以在main.cpp中找到test.cpp定义的数组;

总结:

本篇简要介绍了数组的常用方法以及C++标准库提供的一些关于数组的容器,大家也可以从思考部分来了解数组的一些细节;

来源:https://blog.csdn.net/weixin_40620310/article/details/121369942

标签:C++,数组
0
投稿

猜你喜欢

  • Android登录时密码保护功能

    2023-10-24 07:09:40
  • Java用for循环Map详细解析

    2021-06-08 08:23:03
  • c# DataDirectory的用法

    2021-07-30 14:36:22
  • 关于mybatis if else if 条件判断SQL片段表达式取值和拼接问题

    2023-02-04 18:51:21
  • Java 深入浅出分析Synchronized原理与Callable接口

    2021-11-26 10:27:17
  • 详解Java中对象池的介绍与使用

    2023-07-25 13:13:48
  • Java 中的 String对象为什么是不可变的

    2023-08-04 03:24:32
  • C#抓取网络图片保存到本地的实现方法

    2023-06-28 11:35:13
  • SpringBoot整合Shiro两种方式(总结)

    2021-09-08 21:28:24
  • Android 文件数据存储实例详解

    2023-07-28 17:08:03
  • Docker搭建前端Java的开发环境详解

    2023-05-21 04:23:25
  • springboot项目中使用Swagger的简单示例

    2023-01-14 05:18:24
  • 使用递归实现数组求和示例分享

    2023-04-24 02:17:40
  • Spring Cloud中Sentinel的两种限流模式介绍

    2021-11-22 00:38:10
  • java自定义封装StringUtils常用工具类

    2022-09-01 05:11:13
  • java编程之基于SpringBoot框架实现扫码登录

    2023-02-14 02:39:28
  • VSCode中开发JavaWeb项目的详细过程(Maven+Tomcat+热部署)

    2022-10-18 14:42:10
  • 详解Android自定义控件属性

    2023-09-27 18:00:34
  • SpringBoot + validation 接口参数校验的思路详解

    2023-10-09 11:59:12
  • 用JAVA实现杨辉三角实例

    2023-08-28 16:45:23
  • asp之家 软件编程 m.aspxhome.com