C++(二)

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/dcrmg/article/details/83512135

函数指针

函数指针是指向函数的指针。
函数具有可赋值给指针的物理内存地址,一个函数的函数名就是一个指针,它指向内存中存放函数代码块的起始地址。


函数指针的定义:
类型 (*指针变量名)(参数列表);

例如:
        int (*p)(int i,int j);

这里定义了一个函数指针,该函数具有两个int类型的参数,返回类型为int,指针名称是p,指针符号*跟指针名称用括号括在一起

注意定义函数指针时参数列表不能省!


函数指针用处

  • 1. 通过函数指针调用函数;
  • 2. 可以将函数作为参数传递给另一个函数,实现回调功能;

在程序中,函数名称就代表了该函数所在的起始地址。
使用函数指针调用函数时,直接用指向该函数的指针(*p)代替原函数名称即可,或者直接用p代替原函数名称(推荐使用前者)。

int func(int i, int j);
int (*p)(int i, int j);
p = func;
int a = (*p)(1,2);
int b = p(1,2);


指针函数
指针函数是一个函数, 它的返回值是一个指针。

int* f(int i, int j)  //指针函数
int (*p)(int i, int j)  //函数指针


回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
回调函数的两个重点

  • 1. 通过函数指针调用;
  • 2. 被另外一方调用,对事件进行响应;

回调函数(*p)被调用时,不能在 *p 后直接跟回调函数的参数,而是应该直接传入 *p, 它的参数是作为调用回调函数的函数的参数传入的。

#include<iostream>
using namespace std;

int fun(int i, int j)
{
    return i+j;
}

int callback_f(int(*p)(int, int), int a, int b)
{
    return (*p)(a , b)>= a?(*p)(a , b ):a;
}

int main()
{
    int (*p)(int i, int j);
    p = fun;
        //p = &fun; //is ok

    int val = callback_f(*p,1,2);
    val = callback_f(p,1,2);
    val = callback_f(fun,1,2);

    cout<<val<<endl;
}

 

二维数组、数组指针、指针数组

二维数组
二维数组在存储时按行优先连续存储,如 int a[2][5] 表示该二维数组有两行,即可分为两个一维数组,每个一维数组又包含5个int元素。二维数组本质上是以数组作为数组元素的数组,即“数组的数组”。

一维数组中数组名是数组中第一个元素的指针,指向第一个元素。

二维数组中数组名是二维数组中第一个一维数组的指针,指向第一个一维数组。

    int array1[5] = {5,4,3,2,1};
    int array2[2][3] ={{6,5,4},{3,2,1}};
    
    cout<<array1<<endl;   //输出一维数组的第一个元素的内存地址
    cout<<array2<<endl;   //输出二维数组的第一个数组的内存地址
    
    cout<<*array1<<endl;  //输出一维数组第一个元素的值
    cout<<*array2<<endl;  //输出二维数组中第一个一维数组中第一个元素的地址
    cout<<**array2<<endl; //输出二维数组中第一个一维数组中第一个元素的值

    cout<<*(array1+1)<<endl;  //输出一维数组中第二个元素的值
    cout<<**(array2+1)<<endl; //输出二维数组中第二个一维数组中第一个元素的值

数组指针是指向数组的指针,这里的数组限定是一维的,所也也称数组指针也称为指向一维数组的指针,或称为行指针。

    int array1[5] = {5,4,3,2,1};
    int array2[2][3] ={{6,5,4},{3,2,1}};
    
    int (*p)[5];
    int (*p2)[3];

    p = &array1;
    p2 = array2;

    cout<< *p<<endl;  //输出一维数组中第一个元素的内存地址
    cout<< **p<<endl;  //输出一维数组中第一个元素
    cout<< *(*p+1)<<endl;  //输出一维数组中第二个元素

    cout<< p2<<endl;  //二维数组的内存地址
    cout<<**p2<<endl; //二维数组中第一个一维数组的第一个元素的值
    cout<<**(p2+1)<<endl; //二维数组中第二个一维数组的第一个元素的值

以下输出是“5”。  

    int a[5] = {1,2,3,4,5};
    int* ptr = (int*)(&a+1);
    cout<<*(ptr-1)<<endl;

指针数组定义: int* p[10];


malloc、free 和 new、delete

malloc、free是C/C++的标准库函数, new、delete是C++的运算符,他们都用于申请和释放动态内存。
对于非内部数据类型的对象(如类)而言,对象在创建和销毁的时候需要自动执行构造函数和析构函数, malloc是库函数,不是运算符,不能完成构造和析构功能。

库函数和运算符区别

运算符是语言本身的特性,编译器清楚运算符的操作细节。
库函数是依赖于特定库的,在一定程度上是独立于语言本身的。理论上,编译器不知道也不关心函数具体实现的功能和函数里边的操作,编译器只负责编译正确。

this指针

一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。

一个类可以实例化多个对象,每个对象有自己独立的数据区,但是代码区是对象之间共享的,那么多个对象调用同一段函数代码段,是如何区分各个不同对象自己的数据区呢?这时候就需要使用this指针,this指针指向调用该函数的不同对象本身。

猜你喜欢

转载自blog.csdn.net/dcrmg/article/details/83512135
今日推荐