“造地基”的C++ (七) 指针和动态内存分配

指针和动态内存分配

一,内存空间的访问方式:

  1. 通过变量名访问
  2. 通过地址访问

 

  • 指针的概念(地址类型的变量)
  1. 指针:内存地址,用于间接访问内存地址
  2. 指针变量:用于存放地址的变量

语法: int i;     int *ptr = &i;         &是取地址符    *表示所定义的变量是指针

                                   Int*  表示这个指针所指向的对象是int类型

       *ptr = 3;  这是一个指针运算,寻址的过程,以ptr内容为地址,去寻找地址所指向的目的地。  等价于 i = 3;

    3.与地址相关的运算

     指针运算符:*   指针类型变量内容的寻址运算   知道地址求内容

     地址运算符:&   知道内容求地址

 

  • 指针的初始化
  1. 语法形式 :  存储类型  数据类型  *指针名  =  初始地址 ;
  2. 例:  static  int  *pa  =  &a;
  3. 注意事项:
    用变量地址做为初值时,该变量必须已经在指针初始化之前就声明过,且变量类型应与指针类型一致。可以用一个已有合法值的指针去初始化另一个指针变量。不要用一个内部非静态变量去初始化static指针。

 

整数0可以赋给指针,表示空指针

 

指向常量的指针 :  const int *p = &a;     只能通过指针去访问常量,不能改变常量

指针类型的常量: int * const p = &a;   可以改变指针指向的变量的值,不能改变指针的值

 

  • 指针类型的算术运算
  1. 指针p加上或减去n:其意义是指针当前指向位置的前方或后方第n个数据的起始位置
  2. 指针的++、--运算:意义是指向下一个或前一个完整数据的起始
  3. 当指针指向连续存储的同类型数据时,指针与整数的加减运算和自增自减运算才有意义

 

  • 定义指向数组元素的指针
  1. 定义与赋值

例:  int a[10] , *pa;  pa = &a[0]; 或 pa = a;

2,等效的形式

    *pa就是 a[0], *(pa + 1) = a[1]......

    a数组的名字就是数组的首位地址

所以,a[i] = pa[i] = *(pa + i) = *(a+i)                                

 

  • 指针数组
  1. 指针数组:数组元素是指针类型
  2. 例:Point *pa[2];   由pa[0]和pa[1]组成
  3. 数组的名字就是数组第一个元素的地址

 

  • 以指针作为函数参数

为什么需要指针做参数:

需要数据双向传递的时候(引用也可以达到此效果)

需要传递一组数据,只传首地址运行效率比较高

 

  • 指针类型的函数
  1. 定义:若函数的返回值是指针,则该函数是指针类型的函数
  2. 语法形式:  存储类型 数据类型 *函数名() { //函数体 };
  3. 不要将非静态的局部地址作为函数的返回值,i在子函数中定义局部变量后将其地址返回给主函数,就是非法地址。返回的指针要确保在主调函数中是有效的合法的地址。

 

  • 指向函数的指针
  1. 定义:函数指针指向的是程序代码存储区
  2. 语法形式:   存储类型 数据类型 (*函数指针名)() { //函数体 };
  3. 函数指针的典型用途——实现函数回调

   通过函数指针调用的函数:例如将函数的指针作为参数传递给函数,使得在处理相似事件的时候可以灵活的使用不同德方法

   调用者不关心谁是被调用者:只需知道存在一个具有特定原型和限制条件的被调用函数

 

  • 对象指针
  1. 通过对象指针访问对象成员: 对象指针名 -> 成员名

                              Ptr -> getX()  相当于   (*ptr).getX();

     2.   this指针

  隐含于类的每一个非静态成员函数中

  指出成员函数所操作的对象:当通过一个对象调用成员函数时,系统先将该函数的地址赋给this指针,然后调用成员函数,成员函数对对象的数据进行操作时,就隐含的使用了this指针。

 

 

  • 动态内存分配(不知道程序运行时要处理的数据规模有多大,就用动态内存分配)
  1. 动态申请内存操作符new

   New 类型名T (初始化参数列表)

   功能:在程序执行期间,申请用于存放T类型对象的内存空间,并以初值列表赋初值

   结果值:成功:T类型的指针,指向新分配的内存。失败:抛出异常

     2.释放内存操作符delete

   Delete 指针p

   功能:释放指针p所指向的内存,p必须是new操作的返回值

 

  • 申请和释放动态数组
  1. 分配:new 类型名T【数组长度】

         数组长度可以是任何整数类型表达式,在运行时计算。

     2.释放:delete【】 数组名p

         释放指针p所指向的数组,p必须是用new分配得到的数组首地址

     3.将动态数组封装成类

   在构造函数中申请动态内存,在析构函数中释放所申请的动态内存

 

  • vector对象
  1. 为什么需要vector:封装任何类型的动态数组,自动创建和删除。数组下标越界检查
  2. 定义:  vector <元素类型> 数组对象名(数组长度)

            Vector <int> arr(5);   建立大小为5的int类型数组

     3.对数组元素的引用:

对象名【下标表达式】       vector数组对象名不表示数组首地址

     4.获得数组长度

Vector对象名.size();

 

  • 浅层复制与深层复制
  1. 浅层复制:实现对象间数据元素的一一对应复制(复制构造函数)
  2. 深层复制:当被复制的对象数据成员是指针类型时,不是复制该成员本身,而是将指针所指对象进行复制。

 

  • 移动构造

之前,如果要将源对象的状态转移到目标对象只能通过复制,在某些情况下,我们没有必要复制,只需要移动他们。

 

  • 从键盘写入字符串

      String类型  

      Getline( cin, 将字符串存入的变量名,以什么符号作为结束)

 

  

 

猜你喜欢

转载自blog.csdn.net/ndliuning/article/details/81273353