指针

1.指针初始化(3种情况)
//初始化空指针(一般用Null)
int *P = Null;

//初始化同类型变量的地址
int ival = 2;
int *P = &ival;

//初始化同类型的另一个有效指针
int ival = 2;
int *P = &ival;
int *p2 = P;
2.void* 指针

特点: 可以保存任何类型对象的地址
void* 指针只支持几种有限的操作:
1. 与另一个指针比较。
2. 向函数传递void* 指针或从函数返回void* 指针。
3. 不允许使用void* 指针操纵它所指向的对象

3.指针和引用比较

指针和引用都可以间接访问另一个值,但是是有区别的。
1. 定义引用时没有初始化是错误的
2. 引用一经初始化就始终指向同一特点对象,给引用赋值时修改的是引用所关联的对象的值,而不是使引用与另一个对象关联。

4.指向指针的指针

某一指针的存储地址,可存放在另一个指针中。

#include<iostream>
using namespace std;
int main()
{
    int ival = 100;
    int *Pi = &ival;
    int **PPi = &Pi;//指向指针的指针

    cout<< "ival=" << ival <<endl;
    cout<< "Pi指向的值=" << ival <<endl;
    cout<< "PPi指向的指针所指向的值=" << ival <<endl;//最终都是输出100

    return 0;
}
5.函数返回指针(决不能返回局部变量的指针)

主要原因在于函数中的局部变量在函数返回之后就会被清空,所以是返回不出函数的。

int* fp()
{
    int local = 3;
    return &local;
}

//当然也不能返回局部对象的引用
const string& f(const string& s)
{
    string ret = s;
    return ret;
}
6.指向函数的指针
//============================================================================
// Name        : InsertSort.cpp
// Author      : YL
// Version     :
//============================================================================
#include <iostream>
using namespace std;

void (*SORT)(int n);
//void *SORT(int n); 这样声明是不行的,这样声明仅仅只是声明一个函数其返回值是void* 的指针。
void Sort1(int n){printf("冒泡排序\n");}
void Sort2(int n){printf("希尔排序\n");}
void Sort3(int n){printf("快速排序\n");}

void TestFunPointer()
{
    SORT = Sort1; SORT(1);//SORT = Sort1; (*SORT)(1);  所以也可以这样写
                          //SORT = &Sort1; (*SORT)(1); 所以也可以这样写,这两个组合一些有四种方式都可以(C++中)
    SORT = Sort2; SORT(1);
    SORT = Sort3; SORT(1);
}

int main()
{
    TestFunPointer();
    return 0;
}

Note :对于函数*SORT而言,其函数名为(*SORT)所以一般调用的时候要用(*SORT)(1)这样的形式,但在C++中可以用SORT(1)这个形式,C中必须用(*SORT)(1)。这是对于全局函数而言的,对于类的成员函数来说就不一样了,这个之后再讲。
Note :对于全局函数而言,它的名称就是它的地址,当然直接取地址也仍然表征的是地址,所以上述代码中会有2*2=4种调用方式。然而类的成员函数用的时候必须用取地址符,因为成员函数本质上是变量并不是函数。
Note :当然这种指向函数的指针真正应用的时候会用到typedef限定符,因为这样会比较方便易懂。调用方式如下:

typedef (*PSORT)(int n);
void TestFunPointer()
{
    PSORT sort = Sort1;sort(1);
    (*sort) = &Sort2; (*sort)(1);//这里用到了上面讲的不同种的调用方式。
}
7.指向类的成员函数的指针
//============================================================================
// Name        : InsertSort.cpp
// Author      : YL
// Version     :
//============================================================================
#include <iostream>
using namespace std;
class CA
{
typedef int((CA::*PClassFun)(int ,int));
public:
    int max(int a, int b)
    {
        return a>b? a:b;
    }

        int min(int a, int b)
    {
        return a<b? a:b;
    }

    int Result(PClassFun fun, int a, int b)
    {
        //像上面说的调用类的成员函数的时候必须加上“*”,因为这个函数相当于变量
        return (this->*fun)(a,b);
    }

};

void TestMemberFun()
{
    CA ca;
    int a = 3; int b = 4;
    printf("test member fun\n");
    //所以成员函数必须用&来调用
    printf("max result = %d\n", ca.Result(&CA::max, a,b));
    printf("min result = %d\n", ca.Result(&CA::min, a,b));
}

int main()
{
    TestMemberFun();
    return 0;
}
//输出结果:
//test member fun
//max result = 4
//min result = 3

8.指针操纵二维数组

int b[2][3] = { 1,2,3,21,22,23};
int* p2 = b[0];
此时我们有
// p2[0] = b[0][0] ,p2[1] = b[0][1] ,p2[2] = b[0][2]
// p2[3] = b[1][0] ,p2[4] = b[0][1] ,p2[5] = b[0][2]

#include "stdafx.h"
#include <iostream>
using namespace std;


int main()
{
    int i, j;
    int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };//定义一个二维数组a  
    int b[2][3] = { 1, 2, 3, 4, 5, 6 };//定义一个二维数组b  
    int s[2][3];//声明一个二维数组 s用来存放两个数组的和  
    int *p, *q, *su;//声明三个int类型的指针 用来指向三个二维数组  
    //*****下边是分别指向*****   
    p = a[0];
    q = b[0];
    su = s[0];
    int sum;
    //******用指针来操作二维数组******  
    for (i = 0; i<6; i++)
    {
        sum = p[i] * q[i];
        su[i] = sum;
    }
    //******用数组本身来操作二维数组******  
    printf("the sum of the arrays is \n{");
    for (i = 0; i<2; i++)
    {
        for (j = 0; j<3; j++)
        {
            printf("%d ", s[i][j]);
        }
        printf("\n");
    }
    printf("}");

    getchar();
}