第六节 指针
1. 指针
//目前为止,我们是通过变量来进行数据的传递与运算 //变量的数据操作 int a = 10; float b = 5.3f; double c = a + b; cin >> a; //变量作为参数的函数 int Add(int a, int b); //变量作为参数,调用函数 c = Add(a, b); //数组的声明与使用 int arr[10] = { 0 }; arr[5] = 4; arr[6] = 10; for (int i = 0; i < 10; i++) cout << arr[i]; //以上操作都是“间接”操作,我们并没有直接直接操控计算机内存 //数据的在内存中的创建、修改与释放都是由计算机代为操作的
//计算机基础课程中学习过,计算机中的数据存储包含两个信息 //1. 数据在计算机中的位置,称为内存地址 //2. 数据本身 //C++中指针就是用来直接对内存进行操作的 //指针也是一种变量,指针中存储的数据都是内存地址 //创建一个指向整型变量的指针 int* intPtr; //将该指针指向变量a所在的地址 int a = 123; intPtr = &a; //C++中使用&获取变量的地址,使用*获取指针指向的变量值 //下列两行相同 cout << a; cout << *intPtr;
2. 引用
//在构建函数时,我们使用过引用参数 void Add(int a, int b, int& sum); //引用的意思,就是是两个变量指向同一个地址 int a = 10; int& b = a; b = 50; //由于a和b指向同一个内存地址,因此对b的修改,也会影响a cout << a; //上述操作也可以用指针实现 int c = 10; int* d = &c; //使用*可以获取地址中的值 *d = 50; cout << c;
3. 指针与数组
//在C++中,数组的名字实际上指向数组第一个元素的指针 int a[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* arrPtr = a; cout << *arrPtr << endl; arrPtr++; cout << *arrPtr << endl; arrPtr += 5; cout << *arrPtr << endl; arrPtr += 15; cout << *arrPtr << endl; //由于指针和数组之间的这种关系,如果希望将数组作为返回值时,可以使用指针代替 string* Split(string s, string separators[]); //字符指针与字符串的关系 string s = "Hi"; char* cPrt = &(s[0]); cout << cPrt << endl; cPrt++; cout << cPrt << endl; cPrt += 5; cout << cPrt << endl;
//在使用数组时,必须明确数组的大小 int a[10]; //在使用指针时,可以使用new关键字为指针动态分配数组空间 int* arrPtr; arrPtr = new int[10]; //但是需要特别注意,在使用结束后,需要手动释放这段内存空间 delete[] arrPtr; //注意指向变量的指针和指向数组的指针,释放时语法不同 int* singleParPtr; singleParPtr = new int(5); delete singleParPtr;
4. 指针的类型
在进行程序设计时,很多时候都是先设计整体框架,因此无法给出明确的内存使用大小,但是可以肯定是的该设计内容(变量、函数、结构体等等)肯定会在内存中。
因此在设计时,通常使用各种C++内容的指针,然后在交给其他部门进行具体设计。
#include <iostream> #include <string> using namespace std; int Add() { return 0; } int Add(int* a, int* b) { *a = 22; *b = 33; return *a + *b; } struct Book { char* Title; int ID; }; int main() { // 指针与变量,声明变量指针 type* name; cout << "Var" << endl; int a = 5; int* ptrA = &a; //取址符& *ptrA = 10; //取值符* cout << a << endl; ptrA = NULL; //空指针 cout << ptrA << endl; ptrA = &a; // 指针与数组的关系 cout << "Array" << endl; int arr[10] = {1,2,3,4,5,6,7,8,9,10}; cout << arr[0] << endl; cout << arr[10] << endl; cout << arr << endl; int *ptrArray = arr; cout << ptrArray << endl; cout << *ptrArray << endl; ptrArray++; cout << *ptrArray << endl; // 指针与函数的关系 cout << "Func" << endl; int(*ptrAddFunc)(); int(*ptrAddParFunc)(int*, int*); ptrAddFunc = Add; ptrAddParFunc = Add; cout << Add(&a, &a) << endl; cout << a << endl; // 指针与结构体 cout << "Struct" << endl; Book* book = new Book(); book->ID = 1234; book->Title = "Hello"; Book book1 = Book(); book1.ID = 1235; book1.Title = "World"; cout << sizeof(book) << endl; cout << sizeof(book1) << endl; // 指针与指针 cout << "Pointer" << endl; int **ptrPtrA = &ptrA; cout << a << endl; cout << &a << endl; cout << ptrA << endl; cout << &ptrA << endl; cout << *ptrPtrA << endl; cout << ptrPtrA << endl; return 0; }
5. 练习
//创建两个变量a,b,创建两个指针aPtr,bPtr,并通过指针修改变量的值。 #include <iostream> using namespace std; int main() { int a = 10; int b = 10; int* aPtr = &a; int* bPtr = &b; *aPtr = 5; *bPtr = 5; return 0; }
//创建一个数组,以及一个指向该数组的指针 //利用指针寻找这个数组中最大的元素 #include <iostream> using namespace std; int main() { int a[] = { 1,2,3,4,5,6,7,8,9 }; int* arrPtr = &a[0]; int max = a[0]; for (int i = 0; i < 9; i++, arrPtr++) { if (max < *arrPtr) { max = *arrPtr; } } return 0; }
//创建char指针,指向字符串"A, Pointer" //利用该指针,打印"P"和"r"两个字母 #include <iostream> using namespace std; int main() { char s[] = "A, Pointer"; char* sPtr = s; cout << sPtr << endl << sPtr[3] << endl << sPtr[9]; return 0; }
6. 作业
完成字符串分割函数Split
/// <summary> /// 根据分隔符,分割字符串,返回分割后的字符串数组 /// </summary> /// <param name="s">需要分割的字符串</param> /// <param name="separator">分隔符数组,可以被多个分隔符分隔</param> /// <param name="isIncludeSeparator">分割后的字符串中是否包含分隔符自身</param> /// <returns>分割后的字符串数组</returns> string* Split(string s, string separator[], bool isIncludeSeparator) { }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析