(资料来源:https://www.bilibili.com/video/BV1QE41147RT?p=101)
指针:内存地址,用于间接访问内存单元
指针变量:用于存放地址的变量
static int i ;
static int* ptr = &i ;
语法形式:指针名 = 地址
(在该地址中存放的数据类型与指针类型必须相符)
地址可以是:
通过取地址符&取得已定义的变量的起始地址
动态内存分配成功时返回的地址
整数零,0可以赋给指针,表示空指针,NULL就是被定义为0(C++11中可以使用nullptr代替NULL)
const指针
int a = 1 ;
const int* p1 = &a ;
不能通过指向常量的指针改变所指对象的值,但指针本身可以改变,可以指向别的对象
int a = 1 ;
const int* p1 = &a ;
int b = 2 ;
p1 = &b; // 正确,p1可以指向别的对象
*p1 = a ; // 错误,不能通过p1改变所指向的对象
声明指针常量,指针本身的值不能被改变,也就是说指针指向的地址不能被修改。
int a = 1, b = 2 ;
int* const p2 = & a;
p2 = & b ;// 错误,p2是指针常量,不能改变指针指向的地址
指针p加上获减去n(p + n、p - n)
指针的++、--运算 (p++、p--)
运算的结果取决于指针指向的数据类型,总是指向一个完整数据的起始位置
指针数组:数组的元素是指针类型
int* p[2] ;
// p[0], p[1]分别是两个指针
例子:使用指针数组存放矩阵
#include <iostream>
using namespace std ;
int main() {
int arr1[] = {1,2,3} ;
int arr2[] = {4,5,6} ;
int [] = {1,2,2} ;
int* allArr[3] = {arr1, arr2, } ;
for (int i = 0;i < 3;i++) {
for (int j = 0;j < 3;j++) {
cout << allArr[i][j] << " " ;
}
cout << endl ;
}
return 0;
}
/*
1 2 3
4 5 6
1 2 2
*/
指针数组和二维数组对比
例子
#include <iostream>
using namespace std ;
void splitFloat(float x, int* intPart, float* fracPart) {
*intPart = static_cast<int>(x) ; //获取x的整数部分
*fracPart = x - *intPart ; // 获取x的小数部分
}
int main() {
cout << "Enter 3 float point numbers:" << endl ;
for (int i = 0; i < 3; i++) {
float x, f ;
int n ;
cin >> x ;
splitFloat(x, &n, &f) ;
cout << "Integer Part = " << n << " Fraction Part = " << f << endl ;
}
return 0;
}
/*
Enter 3 float point numbers:
2.333
Integer Part = 2 Fraction Part = 0.333
4.999
Integer Part = 4 Fraction Part = 0.999
2.111101
Integer Part = 2 Fraction Part = 0.111101
*/
若函数的返回值是指针,该函数就是指针类型的函数
注意,不能将非静态局部变量的地址当作函数的返回值,因为非静态局部变量在函数运行结束后就被释放,此时返回的地址是一个非法地址
返回的指针要确保在主调函数中是有效、合法的地址
主函数中定义的数组,在子函数中对该数组元素进行各种操作后,返回其中一个元素的地址 √
#include <iostream>
using namespace std ;
// 找到数组中第一个为0的元素地址
int* search(int* a, int n) {
for (int i = 0;i < n;i++) {
if (a[i] == 0) {
return &a[i] ; // 返回的地址指向的元素是在主函数中定义的
}
}
return nullptr ;
}
int main() {
int arr[5] ; // 主函数中定义的数组
for (int i = 0;i < 5;i++) {
cin >> arr[i] ;
}
int* zeroptr = search(arr, 5) ; // 将主函数中数组的首地址传给子函数
if (zeroptr == nullptr) {
cout << "No element with value 0 was found" << endl ;
} else {
cout << "The address of the element with a value of 0 is " << zeroptr << endl ;
}
return 0;
}
/*
2 3 4 1 0
The address of the element with a value of 0 is 0x6ffe00
*/
在子函数中通过动态内存分配new操作取得的内存地址返回给主函数是合法有效的,但是要记得delete释放内存,避免内存泄漏
定义形式
存储类型 数据类型 (*函数指针名) () ;
含义
函数指针指向的是程序代码存储区
函数指针的用途——实现函数回调
通过函数指针调用的函数
例如将函数的指针作为参数传递给一个函数,使得在处理相似事件的时候可以灵活的使用不同的方法
sort(a, a + n, cmp) // cmp就是通过函数指针调用的函数
调用者不关心谁是被调用者
#include <iostream>
using namespace std ;
int compute(int a, int b, int(*func)(int, int)) {
return func(a, b) ;
}
int max(int a, int b) {
return ((a > b) ? a : b) ;
}
int min(int a, int b) {
return ((a < b) ? a : b) ;
}
int sum(int a, int b) {
return a + b ;
}
int main() {
int a,b,res ;
cin >> a ;
cin >> b ;
res = compute(a, b, &max) ;
cout << "Max of " << a << " and " << b << " is " << res << endl ;
res = compute(a, b, &min) ;
cout << "Min of " << a << " and " << b << " is " << res << endl ;
res = compute(a, b, &sum) ;
cout << "Sum of " << a << " and " << b << " is " << res << endl ;
return 0 ;
}
/*
2 3
Max of 2 and 3 is 3
Min of 2 and 3 is 2
Sum of 2 and 3 is 5
*/
对象指针定义形式
类名* 对象指针名 ;
#include <iostream>
using namespace std ;
class Point {
public :
Point(int x = 0, int y = 0) : x(x), y(y) {}
int getX() const {
return x ;
}
int getY() const {
return y ;
}
private:
int x, y;
} ;
int main() {
Point a(4,5) ;
Point* p1 = &a ; // 定义对象指针,用a的地址初始化
cout << p1->getX() << endl ; // 用指针访问对象成员
cout << a.getX() << endl ; // 用对象名访问对象成员
return 0;
}
/*
4
4
*/
隐含于类的每一个非静态成员函数中
指出成员参数所操作的对象
// 上面的例子,getX()函数中
return x;
// 相当于
return this->x ;
原文:https://www.cnblogs.com/Suans/p/14482516.html