C++ 指针类型

来源:互联网 发布:数据时代的利与弊作文 编辑:程序博客网 时间:2024/05/24 08:34

指针,用来描述内存地址,并通过提供指针操作来实现与内存相关的程序功能。

1. 定义

    <类型>* <指针变量>;

    类型决定了指向的内存空间的大小。

    指针变量也是一种变量,有着自己的内存空间,该空间上存储的是另一个变量的内存空间。

    可以使用typedef取别名来减少定义变量时的一些麻烦,如typedef int* Pointer;


2. 操作

    1)取地址

        ‘&’

        int* p; int x; p = &x;//p指向x的地址,p的类型是int*, &x的类型也是int*

    2)间接访问

         对于一般的指针变量,访问格式是:*<指针变量>

         结构类型的指针变量,访问格式是:(*<指针变量>).<结构成员>  或 <指针变量>-><结构成员>

    3)赋值

          任何类型的指针都能赋给void *类型的指针变量,而非void * 类型的指针变量只能接受同类型的赋值。

    4)指针运算

           一个指针加上或减去一个整型值:<数据类型>* <指针变量>; int a; <指针变量>+a;可以理解为数组中下标的变化,

<指针变量> = <指针变量>+(a*sizeof(<数据类型>))

           两个同类型的指针相减:结果是整型值,对应的是存储空间中元素的个数,可用于求数组的大小。

           两个同类型的指针比较:比较的是存储内容(也就是内存地址)的大小,可用于数组求和等。

    5)指针的输出

          非char *类型的指针变量:cout<<p;//输出的是p存储内容(内存地址) cout<<*p;//输出的是p存储内容上的内容

          char *类型的指针变量:cout<<p;//输出的是以p为起始地址的字符串,这种用法在字符串变化中很常见  cout<<*p;//输出的是p上的一个字符


3. 指向常量的指针变量

const <类型> *<指针变量>;

    含义:不能改变指向的地址上的值(无论该地址上是常量还是变量),但是该变量的值是可以改变的。

    

4. 指针与动态变量

    动态变量是在程序运行时才产生,并在程序结束前消亡。动态变量跟局部变量不同,在程序运行前编译程序就知道了局部变量的存在

    创建:

new <类型名>;  如:int *p; p=new int; *p=1;

new <类型名>[<整型表达式1>]...[<整型表达式n>];  如:int (*q)[20]; int n=5;q=new int[n][20];

void *malloc(unsigned int size);  如:double *q; int n=2; q=(double *)malloc(sizeof(double)*n);

    撤销:因为动态变量不能自动消亡,需要显示撤销其内存空间。

delete <指针变量>;  如:int *p=new int; delete p;

delete []<指针变量>;  如:int *p=new int[20]; delete []p;

void free(void *p);  如:int *p=(int *)malloc(sizeof(int)*6)

    应用:动态数组、链表


5. 指针 VS 无符号整数

    指针从形式上看属于无符号数,但是指针可以关联到程序实体(变量或函数),指针指向某个内存地址,无符号整数的某些运算不能实施在指针上(如乘法和除法就不能)。


6. new VS malloc

    1)new 自动计算所需分配的空间大小,而malloc需要显示指出。

    2)new自动返回相应类型的指针,而malloc要做强制类型转换。

    3)new会调用相应对象类的构造函数,而malloc不会。

    对于new 和 malloc,如果程序的堆区没有足够的空间可供分配,则产生bad_alloc异常(会返回空指针NULL)。


7. delete VS free

   1)delete会调用析构函数,free不会。

   2)delete或free一个指针时,其实只是从编译器释放了这个地址的内存,但指针仍然指向该地址,此时的指针叫做悬浮指针,悬浮指针不为空指针,依据可以用来赋值或者和使用,所以会产生语义错误。(怎么解决呢?在delete或free后将指针设置为NULL)。

   3)如果没有进行delete或free操作,就将指针指向别处,之前分配的内存空间就会一直存在但不能再被使用,也就是说造成了内存泄漏


8. 函数指针

    函数指针就是指向函数的指针。

    定义格式:<返回类型> (*<指针变量>)(<形式参数表>); 如:double (*fp)(int); double fun(int x); fp=&fun;

                   或 typedef <返回类型> (*<函数指针类型名>)(<形式参数表>);  <函数指针类型名> <指针变量>; 如:typedef double (*FP)(int); FP fp;

    使用:(*<指针变量>)(<形式参数表>); 如 (*fp)(10); 相当于 fun(10);

    为什么使用函数指针:可以实现多态,一个函数指针指向不同的函数就可以实现不同的功能,可以结合设计模式理解。

                                          可以向函数传递函数,如:int func(int (*fp)(int)){};


9. 指针与数组

    对数组元素的访问通常是通过下标来实现的,但是频繁地采用这种方式,有时效率不高,因为每次访问都要先通过下标计算数组元素的地址(就是上面的提到的指针变量加上一个整型数)。


10. 多级指针

    指针除了可以指向一般类型的变量外,还可以指向指针类型的变量。指针变量要初始化后才能使用。

    如果一个指针变量没有初始化或者赋值,访问它所指向的变量将会导致运行时刻的严重错误。

int x;

int *p;

int **q;

*p=1; //Error, p未初始化,p指向的空间不知道是什么

*q=&x; //Error,q未初始化

q=&p; //OK

**q=2; //Error, q指向的变量p未初始化


11. 指向常量的指针类型 VS 指针类型的常量

     指向常量的指针类型:不能改变指向的内容。如:const int *p;

     指针类型的常量:指向的地址不能发生改变,内容可以改变,但是必须要初始化。如 int x; int *const q=&x;

     两者结合:const int*const r;

0 0
原创粉丝点击