C++ Primer 笔记——数组
1.数组的大小是固定不变的,声明时必须指定大小(或者使用列表初始化),而且大小必须大于0,C++ Primer里面也建议,如果不确定元素的个数,请使用vector。
int arr[];
int arr1[] = { , , }; //数组长度固定为3
2.和内置类型一样,如果在函数内部定义了某种内置类型的数组,那么默认初始化会令数组含有未定义的值,例如:
int main(int argc, char *argv[])
{
int arr[3];
for(int i : arr)
std::cout << i << std::endl; getchar();
return 0;
}
输出结果为:
3.如果用列表初始化的方式显示的初始化了数组,哪怕没有初始化所有元素,未被初始化的成员也会被赋予默认值,例如:
int main(int argc, char *argv[])
{
int arr[] = {,};
for(int i : arr)
std::cout << i << std::endl; getchar();
return ;
}
输出结果为:
4.定义数组时必须指定数组类型,不可以使用auto
5.数组存放的是对象,所以没有引用的数组
6.用字符串给字符数组初始化时需要注意给结尾的空字符留一个位置,像如下语句是错误的:
char arr[] = "test";
7.数组不允许拷贝和赋值,虽然有些编译器支持数组之间的赋值,但是尽量不要这么做,例如:
int arr[] = { , , };
int arr1[] = arr;
arr1 = arr;
8.一些理解复杂的数组类型:
int *ptrs[]; // pArr 是含有10个整形指针的数组
int &refs[]; // 错误,没有引用的数组
int arr[];
int (*pArr)[] = &arr; // pArr指向一个含有10个整数的数组
int (&refArr)[] = arr; // refArr引用一个含有10个整数的数组
int *(&arr)[] = ptrs; // arr是数组的引用,该数组含有10个指针
C++ Primer提供的理解技巧是从数组的名字开始由内向外阅读,像上面的写法应该先从括号里面读。
9.数组的下标通常定义为 size_t 类型,这是一种与机器相关的无符号类型,它被设计的足够大以便表示内存中任意对象的大小。
数组与指针
1.在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。
int arr[];
auto arr1(arr); //arr1是一个整形指针
auto arr2(&arr[]); //arr2是一个整形指针
在某些表达式中则不会出现这种转换,如decltype:
decltype(arr) arr3; // arr3是一个长度为3的整形数组
2.指针也可以当迭代器使用,但是在指向尾元素的下一个位置的时候不能解引用以及递增操作。
int *e = &arr[]; // e指向arr尾元素的下一个位置
std::cout << *e << std::endl; // 错误,不能解引用
for (int *b = arr; b != e; b++)
std::cout << *b << std::endl;
3.为了能够方便使用指针,C++ 11引入了 begin 和 end 函数,与迭代器的 begin 和 end 作用相似。
int arr[] = { , , };
int *b = begin(arr); // b指向arr的第一个元素
int *e = end(arr); // e指向arr的尾元素的下一个位置
auto n = end(arr) - begin(arr); // 和迭代器一样,两个指针相减的结果是距离,n的结果为3
需要注意的是两个指针相减的结果是 ptrdiff_t 类型,和 size_t 一样是与机器相关的,但是因为可能存在负值,所以是有符号的类型。
4.和指针一样,如果给数组名加上一个整数,编译器自动将数组名转换为指向第一个元素的指针,并执行加法操作。
int arr[] = { , , };
int *p = arr + ; // p指向arr的第2个元素
5.标准库类型 string 和 vector 的下标都是无符号类型,但是数组的内置下标可以处理负值。
int arr[] = { , , };
int *p = &a[]; // p指向数组的第三个元素
int k = p[-]; // p[-1]是数组的第二个元素
C风格字符串
1.字符串字面值是一种通用结构的实例,这种结构即是C++由C继承而来的C风格字符串。它不一种类型,而是为了表达和使用字符串而形成的一种约定俗成的写法,按此书写习惯的字符串存放在字符数组中并以空字符串('\0')结尾。
2.C语言标准库提供了一些可用于操作C风格字符串的函数,但这些函数不负责严重其字符串参数,所以使用时可能会出现错误:
char cArr = { 'C', '+', '+' }; // 不以空字符结束
std::cout << strlen(cArr) << std::endl; //严重错误,cArr没有以空字符结束
上述语句会产生未定义的结果,strlen可能会沿着cArr在内存中的位置一直找下去,直到空字符才停下来。
3.两个C风格字符串不可以像 string 一样直接比较,需要使用strcmp()。
const char cArr1 = "string 1";
const char cArr2 = "string 2";
if(cArr1 < cArr2) {} // 未定义的,试图比较两个无关的地址
cArr1 + cArr2; // 错误,在相加两个指针
即使使用strcpy strcat等函数,也很难控制数组的大小问题,所以还是建议使用标准库的string而不是C风格字符串。
使用数组初始化vector对象
1.不允许使用vector初始化数组,但是允许使用数组初始化vector
int iArr[] = { , , };
std::vector<int> iVec(begin(iArr), end(iArr));
std::vector<int> isubVec(iArr+, iArr+);
多维数组
1.多维数组的初始化规则和一维数组一样。
int iArr[][] = { {}, {}, {} }; // 显示初始化每行首元素,其余默认0
int iArr1[][] = { , , , }; // 显示初始化第一行的元素, 其余行默认0
2.如果表达式含有的下标运算符数量比数组的维数小,则表达式的结果将是给定索引处的一个内层数组:
int iArr[][];
int (&row)[] = iArr[]; // 把row绑定到iArr的第二个4元素数组上
3.要使用for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型,这么做是为了避免数组被转为指针。
int iArr[][] = { };
for (auto &row : iArr)
for (auto col : row)
std::cout << col << std::endl;
4.定义指向多维数组的指针时,千万别忘了这个多维数组实际上是数组的数组。
int iArr[][];
int *p[]; // 整形指针的数组
int (*ip)[]; // 指向含有4个整数的数组
ip = &iArr[]; // ip指向iArr的尾元素
5.类型别名简化多维数组的指针
// 下面两个语句的作用都是将int_array声明为一个4个整数的数组
using int_array = int[];
typedef int int_arry[];
C++ Primer 笔记——数组的更多相关文章
- C++ Primer笔记
C++ Primer笔记 ch2 变量和基本类型 声明 extern int i; extern int i = 3.14;//定义 左值引用(绑定零一变量初始值,别名) 不能定义引用的引用:引用必须 ...
- C++ Primer 笔记——动态数组
1.动态数组定义时也需要指明数组的大小,但是可以不是常量. int i; int arr[i]; // 错误,数组的大小必须为常量 int *p = new int[i]; // 正确,大小不必是常量 ...
- C++ Primer笔记(一):字符串、向量和数组
3.1 命名空间 using namespace::name; using namespace::std using std::cin -- 头文件不应该包含using 3.2 类型string ge ...
- C++ Primer 笔记(1)基础中的战斗机 输入输出 对输入不定数据处理
今天打算再重新好好的看一遍C++ Primer这本很经典的书籍,笔记开始: 1.每个C++程序都包含一个或者多个函数,其中必须有一个main,操作系统通过调用main入手运行程序: 2.函数包括:返回 ...
- C++Primer笔记(3)
标准库类型string表示可变长的字符序列,使用前先包含string头文件.(哈哈,终于可以逃脱C语言中的str函数系列了.)因为是标准库的一部分,所以string被定义在命名空间std中.所以你懂该 ...
- Java菜鸟学习笔记--数组篇(三):二维数组
定义 //1.二维数组的定义 //2.二维数组的内存空间 //3.不规则数组 package me.array; public class Array2Demo{ public static void ...
- C++ Primer 笔记 第一章
C++ Primer 学习笔记 第一章 快速入门 1.1 main函数 系统通过调用main函数来执行程序,并通过main函数的返回值确定程序是否成功执行完毕.通常返回0值表明程序成功执行完毕: ma ...
- C++primer笔记之顺序容器
最近又重新拾起C++primer,发现每一次看都会有不同的体验,但每一次看后因为不常用,忘记得很快,所以记笔记是很关键的一环,咋一看是浪费时间,实际上是节省了很多时间.下面就把这一节的内容做一个简单的 ...
- c++ primer 笔记 (一)
昨天开始看的<C++ Primer>,确实不错.希望这周抓紧看完,每天做下笔记,以便以后复习. main函数返回一个值给操作系统 操作系统通过main函数返回的值来确定程序是否成功执行 ...
随机推荐
- Javascript - ExtJs - 事件
事件(ExtJs Event) Ext.Util.observable类 Ext.Util.observable是一个接口,为Ext组件的事件提供了支持,组件的事件不同于传统事件,所以需要有这么一套 ...
- 微信小程序获取手机验证码
一种比较常见的功能获取手机验证码 先看效果图: 其实这个功能实现起来很简单,主要就是调取第三方接口,拿到返回值验证的问题 直接上代码吧: wxml页面: <view class='changeI ...
- bash常用指令(未完)
#号注释1.man 2.cd 3.clear 4.alias 命令别名设置 区别命令别名和变量的区别,别名可以直接执行,本质是一个函数的索引 5.grep 查找字符串 grep [-acinv] [- ...
- openstack Q版部署-----虚拟机创建(8)
一 .创建网络环境 环境变量生效一下 创建一个网络: openstack network create --share --external \ --provider-physical-network ...
- 异常:已引发: "设置 connectionId 时引发了异常。" (System.Xaml.XamlObjectWriterException) 引发了一个 System.Xaml.XamlObjectWriterException: "
项目中,引用一个富文本编辑器,SmithHtmlEditor,进入页面的时候异常. 在View和ViewModel所在的类库引用. 还需要在Main中引用.
- 【运维】浪潮服务器一块硬盘显示红色Offline(或者Failed)解决办法
[写在前面] 最近服务器不知道为什么总是出现故障,以前戴尔服务器硬盘出现故障,也就是说硬盘旁边的灯显示为红色的时候,一般情况下都是表示硬盘坏掉了,直接买一块新的硬盘,将坏掉的硬盘拿 ...
- Linux信号-信号集&信号屏蔽字&捕捉信号【转】
转自:https://blog.csdn.net/Lycorisradiata__/article/details/80096203 一. 阻塞信号 1. 信号的常见其他概念 实际执行信号的处理 ...
- zynq linux驱动之PL-PS中断【转】
转自:https://blog.csdn.net/h244259402/article/details/83993524 PC:Windows 10 虚拟机:ubuntu 16.04 vivado:2 ...
- python3+selenium入门03-操作谷歌浏览器
操作谷歌浏览器同样也需要下载相应的driver插件,官网下载.也可以从我的网盘下载,不过可能不是最新的,网盘地址.打开谷歌浏览器的操作和火狐的差不过. from selenium import web ...
- Alpha 冲刺 (7/10)
目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:冲刺7 团队部分 后敬甲(组长) 过去两天完成了哪些任务 界面设计.图标设计 写博客 接下来的计划 准备下周答辩 跟进进 ...