笔记30-40

31.Free和delete对指针的操作

    它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。 发现指针 p 被 free 以后其地址仍然不变(非 NULL) ,只是该地址对应的内存是垃圾,p 成了“野指针”。如果此时不把 p 设置为 NULL,会让人误以为 p 是个合法的指针

32.动态申请的内存是否会自动消亡

在一个子函数中,临时申请的变量会在子函数的结束时自动的消亡,但是用malloc申请的动态内存不会随着子函数的结束而消亡,但是会随着整个程序的结束而被Windows回收。但这也不能保证万无一失。指针消亡了,并不表示它所指的内存会被自动释放。内存被释放了,并不表示指针会消亡或者成了 NULL 指针。

33.野指针的问题

●指针变量没有被初始化。任何指针变量刚被创建时不会自动成为 NULL 指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为 NULL,要么让它指向合法的内存。

●指针 p 被 free 或者 delete 之后,没有置为 NULL,让人误以为 p 是个合法的指针。当继续使用该指针时就会产生意想不到的后果。

     指针操作超越了变量的作用范围。例如:

      class A  

      {   

        public: 

       void Func(void){ cout << Func of class A” << endl; } 

      }; 

      void Test(void) 

      { 

        A  *p; 

           { 

               A  a; 

               p = &a; // 注意 的生命期 

           } 

        p->Func();    // p 是“野指针” 

      }

34.变量的生存范围

一个临时的变量的生存时间就是离它最近的一个大括号结束的时候。因此大括号不可乱用。例如:

  Int a = 1;

  {

      Int b = 0;

  }

  Int c = (a + b);//虽然编译可能通过但实际上b已经消失了,这是编译器问题。

35.Malloc和free的使用规则

   原型:void * malloc(size_t size); 

   malloc 返回值的类型是 void *,所以在调用 malloc 时要显式地进行类型转换,将

void * 转换成所需要的指针类型。

   malloc 函数本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。我

们通常记不住 int, float 等数据类型的变量的确切字节数。因此最好用sizeof()来计算要申请内存的大小。

   原型:void free( void * memblock ); 

    为什么 free 函数不象 malloc 函数那样复杂呢?这是因为指针 p 的类型以及它所指

的内存的容量事先都是知道的,语句 free(p)能正确地释放内存。如果 p 是 NULL 指针,

那么 free 对 p 无论操作多少次都不会出问题。如果 p 不是 NULL 指针,那么 free 对 p

连续操作两次就会导致程序运行错误。 

36.New和delete的使用规则

   Type *varyName = new type(InnitValue);//动态申请一块内存,varyName指向它。并    

                                          //初始化

   Type *pArrayName = new type[100];//创建动态数组,但不能同时初始化。

   Delete varyName;

   Delete []pArrayName;//释放动态数组不要忘记[].

37.两种动态申请内存的方法的区别

   malloc 与 free 是 C++/C 语言的标准库函数,new/delete 是 C++的运算符

   对于非内部数据类型的对象而言,光用 maloc/free 无法满足动态对象的要求。对象

在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于

malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数

和析构函数的任务强加于 malloc/free。

    所以我们不要企图用 malloc/free 来完成动态对象的内存管理,应该用 new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。

    如果用 free 释放“new 创建的动态对象”,那么该对象因无法执行析构函数而可能

导致程序出错。如果用 delete 释放“malloc 申请的动态内存” ,理论上讲程序不会出错,

但是该程序的可读性很差。所以 new/delete 必须配对使用,malloc/free 也一样。

38.内存耗尽的处理 

●判断指针是否为 NULL,如果是则马上用 return 语句终止本函数。

●判断指针是否为 NULL,如果是则马上用 exit(1)终止整个程序的运行。

为 new 和 malloc 设置异常处理函数。

绝对不能姑息内存耗尽的应用程序,否则整个操作系统都会崩溃。

39.使用 const 提高函数的健壮性 

    const修饰函数的参数。如果输入参数采用“指针传递”,那么加 const修饰可以防止意外地改动该指针,起到保护作用。如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加 const 修饰。对于非内部数据类型的参数而言,象 void Func(A a) 这样声明的函数注定效率比较底。因为函数体内将产生 A类型的临时对象用于复制参数 a,而临时对象的构造、复制、析构过程都将消耗时间。为了提高效率,可以将函数声明改为 void Func(A &a),因为“引用传递”仅借用一下参数的别名而已,不需要产生临时对象。但是函数 void Func(A &a) 存在一个缺点:“引用传递”有可能改变参数 a,这是我们不期望的。解决这个问题很容易,加 const

修饰即可,因此函数最终成为 void Func(const A &a)

   用函数修饰函数的返回值。如果给以“指针传递”方式的函数返回值加 const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加 const修饰的同类型指针。如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加 const修饰没有任何价值。

40.指针的越界问题

   Char *p = "hello"//不可越界,该内存在编译时分配。其附近都是不可写的区域,因此越界操作时会显示不可写。(静态内存分配)

   Char *p//野指针,更不可越界读写,因为这会导致操作系统的崩溃。

   Char *p = (char *)malloc(size)//可以越界操作,但是在free(p)时会崩溃。(在堆上分配内存)

   Char p[Size] = "hello"//内存分配和Char *p = "hello"不再同时。这里的内存区域是在程序执行时分配的。可以越界读写,不会显示错误,但这也是危险的。(在栈上分配内存。、

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值