C++|不同场合、不同应用场景的不同类型的指针

指针功能强大,但如果使用不当,也是一个重大隐患。

为了深入理解指针,需要了解指针在不同的场合有不同的应用场景。

先看思维导图:

C++ 不同场合、不同应用场景的不同类型的指针

1 指针与对象

这里的对象是指内存对象,数据存储在内存中的数据对象。

1.1 指针指向普通变量

C++ 不同场合、不同应用场景的不同类型的指针

demo:

int main()
{
    int i = 100;
    int *p;
    p = &i; // 指针指向普通变量
    printf("己值与他值:%x = %x
",p,&i);
}

1.2 指针指向对象

C++ 不同场合、不同应用场景的不同类型的指针

demo:

class Point{
    int x,y;
public:
    Point(int a,int b):x(a),y(b){};
};

int main()
{
    Point p1(100,100);
    Point *pt = &p1; // 指针指向对象
}

1.3 指针指向对象的数据成员

C++ 不同场合、不同应用场景的不同类型的指针

demo:

class Point{
public:
    int x,y;
    Point(int a,int b):x(a),y(b){};
};

int main()
{
    Point p1(4,5);
    int *p = &p1.x; // 指针指向对象的数据成员
}

1.4 类的数据成员指针

C++ 不同场合、不同应用场景的不同类型的指针

demo:

#include 
using namespace std;
class Point{
public:
    int x,y;
    Point(int a,int b):x(a),y(b){};
};

int main()
{
    Point p1(4,5),p2(7,8);
    int Point::*p; // 类的数据成员指针,声明时需要类名限定
    p = &Point::x;
    cout<

2 指针与数组

数组名是一个特殊的指针,首先是做为元素的基址,具有常量性质,然后是在不同的上下文中,具有不同的目标类型:

上下文一:数组名的目标类型是整个数组(当与操作符&、sizeof一起使用时),值为首元素地址;

上下文二:数组名的目标类型是数组元素类型(不与操作符&、sizeof一起使用的其它场合),值为首元素地址;

2.1 指针指向数组元素

C++ 不同场合、不同应用场景的不同类型的指针

demo:

int main()
{
    int a[10];
    int *p;
    int i = sizeof a;   // a表示整个数组
    int (*ap)[10] = &a; // a表示整个数组
    p = a;              // 指针指向数组元素,此时的a就相当于&a[0]
}

数组名的类型转变为元素类型指针(降一维的处理,一维数组的元素类型指针是int*),是因为数组的操作主要是元素的操作,元素的操作在于元素地址的取得(基址+偏移),由元素类型可以确定偏移的步长。

2.2 指向数组的指针

C++ 不同场合、不同应用场景的不同类型的指针

int main()
{
    int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
    int (*p2)[3][4] = &a; // p2与a的目标类型为int[3][4]
    int (*p)[4] = a; // 指向数组的指针,p的目标类型为int[4]
}

数组名的类型转变为元素类型指针(降一维的处理,二维数组a的元素类型指针是int(*)[4],元素类型,也就是指针的目标类型是int[]),是因为数组的操作主要是元素的操作,元素的操作在于元素地址的取得(基址+偏移),由元素类型可以确定偏移的步长。

2.3 指针数组

C++ 不同场合、不同应用场景的不同类型的指针

#include  // 定义了NULL
int main()
{
    int x=2,y=3;
    int a[3] = {89,72,43};
    int *p[4]={&x,&y,NULL,a}; // 指针数组
    int **q = p; // 指针数组名可以赋值给一个二维指针,
    // 因为一维数组名是一个一级指针,而指针数组的元素也是一个一个一级指针
}

3 指针与函数

3.1 函数指针:指向函数的指针

C++ 不同场合、不同应用场景的不同类型的指针

demo:

int f(int,int){return 0;}
int main()
{
    int(*p)(int,int); // 函数指针:指向函数的指针
    p=f;
}

3.2 类成员函数指针

C++ 不同场合、不同应用场景的不同类型的指针

demo:

#include
using namespace std;

class Point{
    int x,y;
public:
    Point(int a,int b):x(a),y(b){};
    int getX()const;
    int getY()const;
};
int Point::getX()const{return x;}
int Point::getY()const{return y;}
int main()
{
    Point p1(4,5),p2(7,8);
    int(Point::*funcPtr)()const; // 类成员函数指针,声明时需要类限定
    funcPtr = &Point::getX;
    cout<<(p1.*funcPtr)()<

3.3 函数的参数为指针

C++ 不同场合、不同应用场景的不同类型的指针

demo:

int f(int arr[],int n){return 0;} // 所谓的数组写法,实质也是一个指针
int g(int*x,int n){return 0;}

int main()
{
    int arr[10];
    f(arr,10);  // 被调函数形参:数组,主调函数实参:数组
    int*p = arr;
    f(p,10);    // 被调函数形参:数组,主调函数实参:指针
    g(arr,10);  // 被调函数形参:指针,主调函数实参:数组
    g(p,10);    // 被调函数形参:指针,主调函数实参:指针
}

3.4 指针函数:指针类型函数

C++ 不同场合、不同应用场景的不同类型的指针

demo:

#include
int*func(int x,int y) // 指针函数:指针类型函数
{
    int *q = (int*)malloc(sizeof(int));
    *q = x*y;
    return q;
}
int main()
{
    int *p=func(2,3);
    free(p);
}

4 指针与指针

4.1 指针的指针

C++ 不同场合、不同应用场景的不同类型的指针

demo:

#include 

int main()
{
    int a=100;
    int *p = &a;
    int* *p1 = &p; // p1是一个指针,指针的元素是一个一级指针int*,所以p1是一个二级指针
    std::cout<<(*p1 == p)<

4.2 指向数组的指针

C++ 不同场合、不同应用场景的不同类型的指针

demo:

int main()
{
    int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
    int (*p)[4] = a; // 指向数组的指针,p的目标类型为int[4]
}

数组名的类型转变为元素类型指针(降一维的处理,二维数组a的元素类型指针是int(*)[4],元素类型,也就是指针的目标类型是int[]),是因为数组的操作主要是元素的操作,元素的操作在于元素地址的取得(基址+偏移),由元素类型可以确定偏移的步长。

首先是指针(*p),然后元素类型是int[4],结合到一起就是int (*p)[4]。

4.3 指针数组

C++ 不同场合、不同应用场景的不同类型的指针

#include  // 定义了NULL
int main()
{
    int x=2,y=3;
    int a[3] = {89,72,43};
    int *p[4]={&x,&y,NULL,a}; // 指针数组
    int **q = p; // 指针数组名可以赋值给一个二维指针,
    // 因为一维数组名是一个一级指针,而指针数组的元素也是一个一个一级指针
}

首先是指针(*q),然后元素类型是int*,结合到一起就是int**q。

5 指针与const

指针构造了数据(变量)之间的一种联系,涉及到己型、己址、己值,他型、他址、他值,当用const修饰指针变量时,const可以修饰他型,也可能修饰己型,或者同时修饰他型、己型。

Syntax

meaning

const T*

pointer to constant object

T const*

pointer to constant object

T* const

constant pointer to object

const T* const

constant pointer to constant object

T const* const

constant pointer to constant object

(区分的关键点在于const位于指针声明符*的前面,则表示const修饰指针的目标类型,表示目标类型不能通过指针去修改,如果const位于指针声明符*的后面,表示修饰自身为常量。)

5.1 指针指向的目标类型为const

表示目标类型的值不能通常此指针去修饰,但并不意味着目标类型是常量类型,如果目标类型本身非const类型,目标类型仍然可以通过自己做左值去修改自身。

C++ 不同场合、不同应用场景的不同类型的指针

demo:

int main()
{
    const int a = 20;
    const int *p1 = &a; //const位于符号*前,表示修饰目标对象
    // 表示目标对象不能通过该指针去修改,
//  *p1 = 1; // error,target type is const
    // can't modify target with p1;
    int b = 30;
    p1 = &b;
//  *p1 = 1; // error
    b=2; // 但如果目标对象是非常量,自身是可以修改的
}

5.2 const指针

C++ 不同场合、不同应用场景的不同类型的指针

demo:

int main()
{
    int a,b;
    int *const p = &a;// const指针,const位于符号*的后面,表示修饰指针自身
//  p = &b; //error
    a = 20;
    *p=100;
}

5.3 目标类型和己型都是const

int main()
{
    int a,b;
    const int /*const*/ * const p = &a;
//  *p = 12; // error,因为目标类型int被const修饰,表示不能通过此指针去修改
    a = 12;
//  p = &b;  // p被const修饰(const位于符号*之后),表示p本身是一个常量
    b=13;
}

5.4 二级指针与const

int main()
{
    int a,b;
    int *p = &a;
    int* const* pp = &p; // non-const pointer to const pointer to non-const int
    int *q = &b;
    pp = &q;
    **pp = 22;
//  *pp = &a; // 不能通过pp来修改*pp
    const int *r = &a;
    int const **qq = &r;
//  **qq = 33;
    *qq = &b;
    const int *s = &b;
    qq = &s;
}

6 指针与泛型:

通常称void*与泛型指针,是一种类型暂定的指针。void*在一个库函数中使用较多,如malloc的返回值类型,qsort()的参数类型。

code demo:

#include 

int main()
{
    void *vp;
    int arr[] = {1,2,3,4,5,6};
    vp = arr; // ① 取得基准地址
    // ② vp解引用和算术运算前需要先转型(确定具体类型)
    *((int*)vp) = 11;
    int *p = ((int*)vp)+1;
    *p = 22;
    *((int*)vp+2) = 33;
    for(int i=0;i<6;i++)
        printf("%d ",*((int*)vp+i));
    getchar();
}

-End-

页面更新:2024-03-07

标签:步长   指针   常量   数组   函数   场合   场景   元素   对象   目标   类型   操作

1 2 3 4 5

上滑加载更多 ↓
Top