#Day5 C++

来源:互联网 发布:网络搏彩 编辑:程序博客网 时间:2024/05/24 02:52

指针

用结构类型的指针变量来访问成员,方法有二

  • (*结构变量).结构成员
  • 结构变量->结构成员

当一个指针与一个整型值进行加减运算时,实际加减的值由指针类型决定。

  • 如 double *p;p-=4;//p的值减4*sizeof(double)
int a[10];int *p;p=&a[0];//则可用p[0],p[1],p[2]来访问数组元素,等价于*(p+0),*(p+1),*(p+2)
  • 两个同类型的指针可以相减,通常用以计算两个指针所指向的数组元素之间有多少个元素

  • 两个同类型的指针之间可以比较大小,比较的是所对应的内存地址的大小

//用指针求数组元素之和int a[10],*p=&a[0],*q=&a[9],sum=0;while(p<=q){   sum+=*p;   p++;}
  • 指针的输出
int a,*p=&a;cout<<p;//输出p的值即a的地址cout<<*p;//输出p指向的值,即a//例外char c[]="ABCD",*q=&c[0];cout<<q;//输出的不是q的值,而是q指向的字符串:ABCDcout<<*q;//输出q指向的字符:Acout<<(void *)q;//输出字符串ABCD的内存首地址//要输出一个字符指针的值,则需要将指针强制类型转换成一个其他类型的指针
char str[]="ABCD";    char *p=&str[0];    cout<<p<<endl;//输出ABCD    cout<<p+1<<endl;//输出BCD    cout<<p+2<<endl;//输出CD    cout<<*p<<endl;//输出A    cout<<*(p+1)<<endl;//输出B    cout<<*(p+2)<<endl;//输出C

指针的主要用法

  • 指针作为参数传递

  • 指针与动态变量

参数

数组作为函数参数传递时,实际传递的是实参数组在内存中的首地址,函数的形参数组不再另外分配内存空间,而是共享实参数组的内存空间。在函数中能够通过形参数组改变实参数组的值。

  • C++的默认参数传递方式是值传递(数组除外)

  • 用指针参数实现实参数值的交换:

void swap(int *x,int *y){    int temp;    temp=*x;    *x=*y;    *y=temp;}
  • 向函数传递实参的地址主要作用是为了提高参数传递的效率

e.g

struct A{     int no;   char name[20];};   void f(A *p){//p为指向结构类型的指针   ...}int main(){   A a;   f(&a);//把结构变量的地址传给函数f   ...}
  • 在C++中把指针作为形参的类型可以产生两个效果:
  • 提高参数传递效率
  • 通过形参改变实参的值

第二种效果用于把函数的计算结果(有多个)通过参数返回给调用者。

  • 想要避免这种效果,可以把形参定义为指向常量的指针,使得函数无法通过指针类型的形参来改变形参的值

e.g

const <类型> *<指针变量>//指向常量的指针类型的定义格式//const的含义是不能改变指针变量所指向的数据的值
//指向常量的指针也可以指向变量const int *p;//p是指向常量的指针const int x=0;p=&x;//OK*p=1;//ERROR//p能指向变量y,但不能通过p改变y的值
//指向变量的指针不可以指向常量const int x=0;int *p;p=&x;//ERROR
void f(const int p[],int num)//或const int *p//在函数f中不能改变数组元素的值

指针类型的常量

int x=0,y;int *const p=&x;//p是一个指向变量的指针常量,指针常量必须要初始化。*p=1//OK,*p是一个变量p=&y;//ERROR,p是一个常量
const int x=0;const int * const p=&x;//不仅指向常量,指针本身也是一个常量
  • 注意:不能把局部量的地址作为指针返回给调用者,因为当函数返回后,其局部变量的内存空间已被收回。
  • 如果调用者在使用这个内存空间中的值之前又调用了某个函数,则该空间将被新调用的函数所使用并拥有了新的值。这样调用者就得不到原来的值了。

指针与动态变量

动态变量需要在程序中显式地创建和撤销,局部变量则是自动生成和消亡的。动态变量的内存空间分配在程序的堆区,局部变量栈区。

动态变量的创建

c++提供了两种创建动态变量的 机制操作符 new和库函数malloc,格式为:

new <类型名>//new操作在程序的堆区产生一个指定类型的动态变量,操作的结果为该动态变量的地址(或指针)。int *p;p=new int;//产生一个动态的整型变量,p指向该变量*p=1;//只能通过指针变量来访问该整型变量
  • new操作的结果是有类型的
  • new int[n1][n2][n3],其中只有n1可以不是常量或常量表达式
    new返回数组首地址
//产生一维动态数组int *p;int n;p=new int[n];

二维:

//产生二维动态数组int (*q)[20];//q为一个指向由20个int型元素构成的一维数组的指针            //等价于typedef int A[20];A *q;int n;q=new [n][20];//等价于q=new A[n];
  • malloc
void *malloc(unsigned int size);//函数malloc在stdlib.h或cstdlib中声明//在程序的堆区中分配一块大小为size的内存空间,并返回该内存空间的首地址,类型为void *//若该空间用于存储某个具体类型的数据,则需对返回值强制类型转换

new与malloc的主要区别

  • new自动计算所需分配空间的大小,malloc需要显式指出
  • new自动返回相应类型的指针,malloc需要强制类型转换
  • 若创建的是动态对象,new需要去调用相应对象类的构造函数,malloc不会

  • 对两者,若堆中没有足够空间,则产生bad_alloc异常(或返回空指针NULL)

动态变量的撤消

  • 作符delete
  • 库函数free
int *p=new int;...delete p;
//撤消指针变量所指向的动态数组变量int *p=new int[20];...delete []p;
//释放p所指向的内存空间void free(void *p)int *p=(int *)malloc(sizeof(int));int *q=(int *)malloc(sizeof(int)*20);......free(p);//撤消p所指向的动态变量free(q);//撤消q所指向的动态数组
  • 不能用free和delete撤消非动态变量,会产生程序异常错误

delete 和free的主要区别

  • 如果p指向的是对象(或对象数组),则delete p(或delete []p)会去调用对象类的析构函数,free(p)不会。
  • delete或free撤消动态变量后,C++编译程序一般不会把指向它的指针置为NULL,这时就会出现一个“悬浮指针”,它指向一个不可用空间。

- 如果一个动态变量不被撤消,只是把指向它的指针变量指向了别处或者指向它的指针变量生存期结束了,则这个动态变量就会变成一个“孤儿”,你访问不到它,它也一直在占用内存。上述现象称为“内存泄漏”。

0 0
原创粉丝点击