C++学习-入门到精通-【6】指针

C++学习-入门到精通-【6】指针


指针


一、指针的初始化

指针在声明或赋值时,应该被初始化为nullptr(C++11的新特性),或是一个相应类型的地址。当一个指针变量的值为nullptr时就称其为空指针。

注意所有使用的指针都应该进行初始化,以防止其指向一个未知的或未被初始化的内存空间

在早期的C++ 版本中,为空指针指定的值为0或者是NULL。NULL在多个标准库头文件中被定义,用来表示值0。

注意:声明中的*不是运算符,它只是表明正在被声明的变量是一个指针

二、指针运算符

地址运算符&

地址运算符是一个一元运算符,它获得操作数的内存地址。例如:

cpp 复制代码
int y = 5; // 声明一个int类型的变量
int *yPtr = nullptr; // 声明一个指向int类型的指针变量,并初始化为nullptr

yPtr = &y; // 将y的地址赋值给yPtr

此时可以说变量yPtr指向yyPtr间接引用变量y的值。

注意区分地址运算符&和引用变量声明中的&

间接引用运算符*

一元的*运算符通常称为间接运算符或间接引用运算符,它返回一个左值,表示其指针操作数所指向的对象。例如:

cpp 复制代码
cout << *yPtr << endl;

该语句输出变量y的值,即5,与下面的语句等价;

cpp 复制代码
cout << y << endl;

提示

间接引用一个空指针或未初始化的指针会导致不确定的行为,而且通常是一个致命的运行时错误,因此,在间接引用之前程序员应该明确知晓这个指针是指向哪里。

使用地址运算符&和间接引用运算符

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
	int a = 7;
	int *aPtr = &a;

	cout << "The address of a is " << &a
		<< "\nThe value of aPtr is " << aPtr << endl;
	cout << "\nThe value of a is " << a 
		<< "\nThe value of *aPtr is " << *aPtr << endl;
}

运行结果:

三、使用指针的按引用传递方式

cpp 复制代码
#include <iostream>

using namespace std;

void cubeByReference(int* x)
{
	*x = (*x) * (*x) * (*x);
}

int main()
{
	int i = 3;

	
	cout << "Cube of " << i << " is ";
	cubeByReference(&i); 
	cout << i << endl;
}

运行结果:

在C++中,所有的参数其实都是按值传递的。以使用指针变量的按引用传递方式传递一个变量实质上并没有按引用传递任何东西,传递的其实是这个变量的指针(这个变量的地址),将该地址复制到函数对应的指针形参中。然后被调函数可以通过间接引用这个指针来访问调用者中的这个变量,从而完成按引用传递。

四、内置数组

标准库函数的begin和end

在之前的章节中我们使用sort函数对一个元素类型为string的array对象进行排序,使用语句如下:

cpp 复制代码
sort(colors.begin(), colors.end());

array类中的begin和end函数指定了排序的范围------整个array对象。对于内置数组而言,我们也可以使用sort对它进行排序,例如:

cpp 复制代码
int n[5] = {5,3,4,2,1};
sort(begin(n), end(n));

注意之前介绍过的基于范围的for语句,它其实也是使用了循环对象的begin和end函数来确定循环的范围。

内置数组的局限性

  • 无法使用关系和相等运算符进行比较。如果要比较两个数组,需要使用循环,一个一个的进行比较;
  • 不能相互赋值;
  • 它们不知道自己的大小。处理一个内置数组的函数通常接收两个参数,一个是这个数组的名字,另一个是这个数组的大小;
  • 它们不提供边界检查功能,需要程序员手动检查是否越界;

五、使用const修饰指针

一个好的程序应该是遵循最小特权原则的,也就是一个函数是有足够的权限访问函数参数中的数据来完成指定的任务的,但是权限不能过大。

在之前写过的代码中我们也遵循着这样的原则,还记得之前使用过的const关键字吗。我们就更通过这个关键字实施最小特权原则的。

例如要打印一个array对象中的元素,但是不需要修改它:

cpp 复制代码
array <int, 5> arr = { 1,2,3,4,5 };

for(const int& item : arr)
{
	cout << item << " ";
}
cout << endl;

上面的例子中使用一个引用变量来访问array对象中的元素,前面加上了一个const表明,在这个作用域中,item这个别名不应该修改它引用的值。这就保证在这个输出函数中,不会出现不合法的修改行为,导致出错。

将指针传递给函数有4种方式:指向非const数据的非const指针、指向const数据的非const指针、指向非const数据的constant指针、指向const数据的const指针;

看上去好像比较复杂,但是通过下图可以很容易的分辨它们:

cpp 复制代码
int * i;
相关推荐
yaoxin5211231 小时前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
凡人叶枫1 小时前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
noipp1 小时前
推荐题目:洛谷 P10907 [蓝桥杯 2024 国 B] 蚂蚁开会
c语言·c++·算法·编程·洛谷
学逆向的2 小时前
C++纯虚函数
开发语言·c++·网络安全
程序员二叉2 小时前
【JUC】ThreadLocal底层原理|内存泄漏|弱引用|跨线程传递方案
java·开发语言·面试·职场和发展·juc
程序员二叉2 小时前
【JUC】线程池全套深度详解|参数|流程|拒绝策略|调优|异常处理
java·开发语言·jvm·算法·面试·juc
凡人叶枫3 小时前
Effective C++ 条款22:将成员变量声明为 private
linux·开发语言·c++
Qt程序员3 小时前
掌握 Linux 内核调度:从原理到实现(进程篇)
java·开发语言
code bean3 小时前
【LangChain】检索器完全指南:从向量检索到生产级 RAG 架构
java·开发语言·微服务
LabVIEW开发3 小时前
LabVIEW + MATLAB 混合编程:爆炸场测试数据精准采集方案
开发语言·matlab·labview