• C++Primer第四版13.5.1. 定义智能指针类的例子被new蒙蔽_BLOCK_TYPE_IS_VALID


    ---“不要delete栈上的地址”

    ---“new 和delete是配对的” 的又一个例子

    ---_BLOCK_TYPE_IS_VALID

     

    以下代码是书上实现智能指针类。

    file:HasPtr.h

    #pragma once

    class HasPtr;

    class U_Ptr// private class for use by HasPtr only 

    {

         friend class HasPtr;

         int *ip;

         size_t use;

         U_Ptr(int *p):ip(p),use(1){}

         ~U_Ptr(){delete ip;}           //这里是delete。“不要delete栈上的地址”。

                                                  //ip由p赋值,所以p需要是new出来的,否则...这里delete就会悲剧了。

    };

     

    class HasPtr

    {

    public:

         HasPtr(int *p,int i):ptr(newU_Ptr(p)),ival(i){}//这个new蒙蔽了我的眼睛,误以为任何情况下ip都是new出来的。

                                                                            //其实....这里用new的效果和目的是:在堆上创建U_Ptr对象,获得这个对象的指针,

                                                                           //赋给指针成员ptr,然后在析构的时候delete ptr才是合理的。

                                                                          //是与析构函数中的delete相配对的。

         HasPtr( const HasPtr& ohp):

         ptr(ohp.ptr),ival(ohp.ival){++ptr->use;}

         HasPtr& operator=(const HasPtr& rhp){

                                 ++rhp.ptr->use;

                                 if (--ptr->use == 0){delete ptr;}

                                 ptr=rhp.ptr;

                                 ival = rhp.ival;

                                 return *this;

                                 }

         ~HasPtr(void){

                if (--ptr->use == 0){deleteptr;}

            }

     

             int *get_ptr() const{ return ptr->ip;}

             int get_int() const { return ival;}//

             void set_ptr(int *p){ ptr->ip = p;}

             void set_int(int i){ ival = i;}//

             int get_ptr_val() const { return *ptr->ip;}

             void set_ptr_val(int i) { *ptr->ip = i;}

    private:

              U_Ptr *ptr;

              int ival;

    };

     

    以下是调用测试代码:

    file:main.cpp

    #include <stdlib.h>

    #include "HasPtr.h"

    int main() 

        //悲剧的写法:

           int baseint = 42;//栈上的baseint

           HasPtr obj1( &baseint,10 );   //悲剧,这样传入的实参就是栈上的baseint的地址,delete它是错误的。

        

        //没错的写法:

         int *basep = new int(42); //new出来的,delete  ip时是正确的。

         HasPtr obj1(basep,10);

      HasPtr obj2(obj1);

     

       return EXIT_SUCCESS;

    }

  • 相关阅读:
    vmware和主机通信方法
    曾经的读书计划
    Linux下的autoconf和automake
    Nor Flash读写方法
    Linux下的动态库和静态库
    asp.net读取Xml文件到DataSet,以及DataSet保存为Xml,利用自带的强大功能
    SqlServer 2000/2005 列转行 行转列收集
    GridView 模板列 在后台获取该行某控件的值 例如批量修改
    C# DllImport的用法 调用Window的一些常用功能
    C#通用数据库操作类 支持Access/MSSql/Orale/MySql等数据库
  • 原文地址:https://www.cnblogs.com/riordon/p/3041034.html
Copyright © 2020-2023  润新知