ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++语言导学 第一章 基础知识 - 1.7 指针、数组和引用

2021-12-19 09:02:13  阅读:144  来源: 互联网

标签:count char 1.7 nullptr C++ 导学 引用 数组 指针


第一章 基础知识

1.7 指针、数组和引用

最基本的数据集合类型就是数组——一种空间连续分配的相同类型的元素序列。这基本上就是硬件所提供的机制。元素类型为char的数组可像下面这样声明:

char v[6];	//含有6个字符的数组

类似地,指针可这样声明:

char* p;	//指向字符的指针

在声明语句中,[]表示“……的数组”,*表示“指向……”。所有数组的下标都从0开始,因此v包含6个元素,从v[0]到v[5]。数组的大小必须是一个常量表达式。一种指针变量中存放着一个对应类型的对象的地址:

char* p = &v[3];	//p指向v的第4个元素
char x = *p;		//*p是p所指的对象

在表达式中,前置一元运算符*表示“……的内容”,而前置一元运算符&表示“……的地址”。可以用下面的图形来表示上述初始化定义的结果。
在这里插入图片描述
考虑将一个数组的10个元素拷贝到另一个数组的任务:

void copy_fct(){
	int v1[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
	int v2[10];						//v2将成为v1的副本
	
	for(auto i = 0; i!=10; i++)		//拷贝元素
		v2[i] = v1[i];
	//...
}

上面的for语句可以这样解读:“将i置为0。当i不等于10时,拷贝第i个元素并递增i”。当作用于一个整型或浮点型变量时,递增运算符++执行简单的加1操作。C++还提供了一种更简单的for语句,称为范围for语句,它可以用最简单的方式遍历一个序列:

void print(){
	int v[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};	
	for(auto x:v)				//对于v中的每个x
		cout<<x<<’\n’;	
	for(auto x : {10, 21, 32, 43, 54, 65})
		cout<<x<<’\n’;
	//...
}

第一个范围for语句可以解读为“从头到尾遍历v的每个元素,将其副本放入x并打印”。注意,当我们使用一个列表初始化数组时,无须指定其大小。范围for语句可用于任意的元素序列。

如果不希望将值从v拷贝到变量x中,而只是令x引用一个元素,则可编写如下代码:

void increment(){
	int v1[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};	
	for(auto& x : v)	//对于v中的每个x加1
		++x;
	//...
}

在声明语句中,一元后置运算符&表示“……的引用”。引用类似于指针,唯一的区别是我们无须使用前置运算符*访问所引用的值。而且,一个引用在初始化之后就不能再引用其他对象了。

当指定函数的参数时,引用特别有用。例如:

void sort(vector<double>& v);	//排序v(v是一个double的向量)

通过使用引用,我们保证在调用sort(my_vec)时不会拷贝my_vec,从而真正对my_vec进行排序而不是对其副本进行排序。

还有一种情况,我们既不想改变实参,又希望避免参数拷贝的代价,此时应该使用const引用。例如:

double sum(const vector<double>&)

函数接受const引用类型的参数是非常普遍的。

用于声明语句中的运算符(如&、*、[])称为声明运算符(declarator operator):

T a[n]	//T[n]:n个T组成的数组
T* p	//T*:p为指向T的指针
T& r	//T&:r为T的引用
T f(A)	//T(A):函数f接受类型为A的实参,返回类型为T的结果

空指针

我们的目标是确保指针永远指向某个对象,这样该指针的解引用操作才是合法的。当确实没有对象可指向或者需要表示“没有对象可用”的概念时(例如,到达列表的末尾),我们赋予指针值nullptr(“空指针”)。所有指针类型都共享同一个nullptr:

double* pd = nullptr;
Link<Record>* lst = nullptr;	//一个Record的Link的指针
int x = nullptr;				//错误:nullptr是个指针,不是整数

接受一个指针实参时检查一下它是否指向某个东西,这通常是一种明智的做法:

int count_x(const char* p, char x)
	//统计x在p[]中出现的次数
	//假定p指向一个以零结尾的字符数组(或者不指向任何东西)
{
	if(p==nullptr)
		return 0;
	int count = 0;
	for(; *p != 0; ++p)
		if(*p == x)
			++count;
	return count;
}

有两点值得注意:一是如何使用++将指针移动到数组的下一个元素;二是在for语句中,如果不需要初始化操作,则可以省略它。

count_x()的定义假定char是一个c风格字符串(C_style string),即,指针指向了一个以零结尾的char数组。字符串字面值中的字符是不可变的,为了能处理count_x(“Hello!”),将count_x声明为一个const char参数。

在旧式代码中,也通常用0和NULL来替代nullptr的功能。不过,使用nullptr能够避免混淆整数(0或NULL)和指针(如nullptr)。

在count_x()例子中,对for语句我们并没有使用初始化部分,因此可以使用更简单的while语句:

int count_x(const char* p, char x)
	//统计x在p[]中出现的次数
	//假定p指向一个以零结尾的字符数组(或者不指向任何东西)
{
	if(p==nullptr)
		return 0;
	int count = 0;
	while(*p){
		if(*p == x)
			++count;
		++p;
	}
	return count;
}

while语句重复执行,直到其循环条件变成false为止。

对数值的检验(例如count_x()中的while(*p))等价于将数值与0进行比较(例如while(*p != 0))。对指针值的检验(如if§)等价于将指针值与nullptr进行比较(如if(p != nullptr))。

“空引用”是不存在的。一个引用必须指向一个合法的对象(C++实现也都假定这一点)。的确存在聪明但晦涩难懂的能违反这条规则的办法,但不要这么做。

标签:count,char,1.7,nullptr,C++,导学,引用,数组,指针
来源: https://blog.csdn.net/qq_40660998/article/details/121893628

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有