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]
数组和指针的转换关系图
指向数值开头的指针很好获得,比如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); // 不可以越界
在标准库中的begin
和end
函数,在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


猜你喜欢
- engine的实现结构elasticsearch对于索引中的数据操作如读写get等接口都封装在engine中,同时engine还封装了索引的
- 本文所述实例为使用伪随机数进行用户密码加密,这段代码为核心部分主要代码,需要配合其它的程序实现,感兴趣的读者可以自己进一步加以完善,不费话了
- 实现效果:注意:using system.io; 往Form1上添加控件picturebox,再添加imagelist,并设置imageli
- 本文实例讲述了Android开发实现读取Assets下文件及文件写入存储卡的方法。分享给大家供大家参考,具体如下:调用一个反编译的.so文件
- 本文实例为大家分享了Java实现FTP上传与下载的具体代码,供大家参考,具体内容如下JAVA操作FTP服务器,只需要创建一个FTPClien
- 使用System.Environment获取电脑的相关属性,入门案例,具体内容如下static void Main(string[] arg
- ListView和GridViewListView,列表视图,是Android中最重要的组件之一,几乎每个Android应用中都会使用Lis
- /// <summary>/// 人民币大写/// </summary>/// <param name=&qu
- 一、分布式压测原理如下图(这个图说明的是要一台控制机,然后由这台控制机发压测脚本到每台远程执行机,然后由控制机收集执行机结果)二、修改 Jm
- Android 使用log4j前言: 如果要直接在android工程中使用log4j,是有点问题的,会报如下的错: 1
- 本文实例为大家分享了java日期时间基本操作方法,供大家参考,具体内容如下1. 获得Calendar实例:Calendar c = Cale
- 在往常的 HTTP 调用中,一直都是使用的官方提供的 RestTemplate 来进行远程调用,该调用方式将组装代码冗余到正常业务代码中,不
- 前言最近看了内部类后,总结一下,首先内部类嵌套在其他内部的类,根据出现的位置和关键字,可以分为以下四种类:成员内部类,静态内部类,方法内部类
- 前言最近遇到一个Jvm old过高的案例,现象是一个站点的jvm old区过高,分析原因是,原来的设计方案有问题,给前端返回的数据里面包含了
- Example官方介绍Query by Example (QBE) is a user-friendly querying techniqu
- private string CheckCidInfo(string cid) &
- 和之前一样首先看一下WPF钟表效果图 是不是很炫酷,上面的那个花都是带有动画效果的图片 。接下来就是代码了。首先看一下整个场景的布局搭建&l
- 0.引言死信队列是消息队列中非常重要的概念,同时我们需要业务场景中都需要延迟发送的概念,比如12306中的30分钟后未支付订单取消。那么本期
- 背景在很多时候我们代码中的一些逻辑操作并不能够硬编码到代码中,我们可能希望通过配置来完成这个操作,所以这个时候我们就需要有一些脚本语言能够处
- 这篇文章主要介绍了Spring自动装配Bean实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要