C++ 指针知识点整理

来源:互联网 发布:中国移动优化工作 编辑:程序博客网 时间:2024/05/24 00:46

学习C++指针部分的知识必须先了解两个符号的含义

a." * ",叫做解析运算符或者解除引用运算符,功能:找到该地址处的值。

(C++指针使用铁律:在用解除运算符 * 之前,必须初始化一个确定、适当的地址,否则可能会出现难以寻找的bug。

例子:long* a;*a=1;这是错的,a的值未确定)

b." & ",叫做地址运算符,功能:获取该变量的地址    

两者功能恰好相反。

(注:&不能用于取符号常量 define 和字面常量的地址,符号常量和立即数都没有地址,常量在预处理时就已经展开成符号标识,是不占用空间的。所占用空间的都是变量。const类型的常量,其不是真正意义上的常量。其只是一个只读的变量。这样就意味着其是占用空间的,所以你使用取地址符还是能够取到其地址的。)


1.声明和初始化指针

指针声明和初始化的通用格式:typeName* pointer_name=&a;
             typeName** pointer_name;(指针的指针的声明)
例子:
#include <iostream>using namespace std;int main(){int a=1;int* p=&a;int** q=&p;cout<<q<<endl;cout<<*q<<endl;cout<<**q<<endl;int b[3];int (*p)[3]=&b;return 0;}

输出结果:
(注:*号与数据类型写在一起便于理解,指针是复合类型,表示指向int的指针,它指向的对象则是它的派生量)
易错点:
a.定义两个指针要注意每个变量前面都要加上 * ,否则变成定义一个指针一个变量。如 int* p1,p2;这是错的,正确的应当为 int* p1,* p2;
b.如何理解指针的指针的定义和使用,如何上面的例子中定义了 p指针和 q指针 ,其中p是整形变量a的指针用 int* 去进行声明,q是指针p的指针即指针的指针用 int** 去声明。虽然两者都是指针,但他们不是同一类型,前者是 int* 类型,后者是 int** 类型,所以当我们把 main函数中 第三句代码改成 int* q=&p;会报错,表示类型不符合。
在举书上一个例子 c++ primer plus (第六版)p119 程序4.23 mixtypes.cpp 中,
const antarctica_years_end* arp[3]={&s01,&s02,&s03};
const antarctica_years_end** ppa=arp;
定义了名称为arp 的指针数组,数组名可以看成指针,它指向数组的第一个元素,这个程序中第一个元素是指针,则arp是指向指针的指针。声明ppa时,需要用上两个 *。
c.不能对指针直接赋值,类型不同。如int* pt;pt=0XB8000000;这是错的,需要强制转换成(int*)类型。

2.指针、数组和指针算数

C++中数组名解释为地址,指针和数组在绝大多数情况等下可以通用:
下面的例子可以说明两者的异同:
#include <iostream>using namespace std;int main(){short a[3]={1,2,3};short* pa=a;//int* pa=&a[0];这两句代码含义一样cout<<*(a+1)<<endl;//数组名当做指针用 相当于 a[1]cout<<pa[1]<<endl;//指针当做数组用 *(pa+1)cout<<sizeof a<<endl;//求a数组的占内存大小cout<<sizeof pa<<endl;//求指针pa占内存的大小return 0;}


运行结果如下图


指针和数组的不同点:
a.在上面的程序程序中可以看出,在 数组a 应用sizeof 的到的是数组a的长度(3*2字节),指针pa得到的是指针的长度 4字节(在一般实现中一个地址4个字节)。
b.指针的值可以修改,而数组名是常量不能修改。

指针的算数运算:
C++允许指针和整数相加,结果是原来地址值加上该指针指向对象的占用的字节数(如上述代码中的cout<<*(a+1)<<endl; a指向的对象是short int 型 占2个字节,所以a+1的地址是a[1]的地址)
也可以进行两个指针的相减,只有在指向同一数组才有意义(也可指向超出结尾的一个位置),将得到两个元素的间隔。见p110.
另外的一些的例子:见p109
short tell[10];
tell(等价于&tell[0])表示一个2字节内存块地址,tell+1加两个字节;&tell表示的是整个数组一个20字节内存块的地址,&tell+1表示加20个字节(书上是&tell+2感觉书上打印错了)。前者指针类型是short* ,后者指针类型是short(*)[10]。short(*pas)[10]=&tell;pas=&tell;*pas 与tell 等价 ,(*pa)[0]是tell数组的一个元素。

3.指针和字符串

先来看一段代码:
#include <iostream>using namespace std;int main(){int a[3]={1,2,3};char b[3]="cd";//C风格代码    也可以char* b="cd"; 第二种方法无元素个数的限制cout<<a<<endl;//显示地址cout<<b<<endl;//显示字符串     cout<<(int*)b<<endl;//强制转换成另一种指针类型,才能显示地址return 0;}
运行结果:

上面说了数组名可以看成指针,为什么输出a是地址而输出b是字符串呢,原因如下:

一般来说,如果给cout提供一个指针,将打印它的地址。但如果指针类型是char*,cout将显示指向的字符串,从该处开始打印字符,直到遇到空字符为止"\0"。如果要显示地址,必须强制类型转换成另一种指针类型如 int*。

那cout<<"cd";该如何理解呢? 引号括起来的字符串像数组名一样,也是第一个元素的地址。


4.C++管理数据内存的方式以及new和delete的使用

C++三种管理数据内存方式:

a.自动存储(存储在栈中)

代码块中(函数内)定义的常规变量使用自有存储空间,被称为自动变量。它是一个局部变量,作用域为代码块(函数内)。代码块(函数)调用时产生,结束时消亡。

这时候new 和 delete 的好处就体现出来了,new和delete对内存有很大的控制权,能方便的控制内存何时释放。

b.静态存储

是整个程序执行期间都存在的执行方式。两种声明方式第一种,定义在函数外。第二种,声明变量时前面加上 static: static int a=1;

c.动态存储

new 和 delete提供了更加灵活的方法,它们管理了一个内存池叫自由存储空间(free store)或堆(heap)

优点:new和delete对内存有很大的控制权,能方便的控制内存何时释放。

缺点:占用自由存储区域不连续,这使得新分陪内存的位置跟困难,效率降低。

new 和 delete的使用规则 :

1.new 和 delete 要配对使用,delete不能重复释放,更不能释放不是用new分配的内存。

2.如果指针用new分配好内存则不能在用delete释放前对其进行更改,否则导致内存泄露。

int* p=new int;

p=&a; //对p进行了更改,将找不到原来分配的内存

3.若为申请动态数组则如下

int* a=new int[3];

delete []a;

4.如果指向的对象是结构,则可以用指针解除应用运算符来(->)访问其成员。

5.对空指针应用delete是安全的



小编水平有限难免有些错误,如果发现尽快与我联系。QQ2415180498


0 0