zoukankan      html  css  js  c++  java
  • C++primer 阅读点滴记录(二)

      智能指针(smart point)

          除了增加功能外,其行为像普通指针一样。 一般通过使用计数(use count)或引用计数(reference count)实现智能指针,防止出现指针垂悬。

    下面是一个普通带指针的类代码:

    #ifndef HASPTR_H
    #define HASPTR_H
    
    class HasPtr{
    public:
        HasPtr(int *p, int i):ptr(p),val(i){}
        int *get_ptr()const{return ptr;}
        int get_int()const{return val;}
    
        void set_ptr(int *p){ptr = p;}
        void set_int(int i){val = i;}
    
        int get_ptr_val()const{return *ptr;}
        void set_ptr_val(int val)const{ *ptr = val;}
    private:
        int *ptr; //common pointer
        int val;
    };
    
    
    #endif // HASPTR_H

      小心地雷:

                    具有指针成员且使用默认合成构造函数的类具有普通指针的所有缺陷。尤其是,类本身无法避免垂悬指针。

     

    一般有两种策略使用引用计数:

    1、单独定义一个具体类用以封装使用计数和相关指针:(一般将该类设为私有类,仅友元类可以访问)

    //private class for use by HasPtr only
    class U_ptr{
        friend class HasPtr;
        int *ip;
        size_t use;
        U_ptr(int* p):ip(p),use(1){}
        ~U_ptr(){delete ip;}
    };
    
    HasPtr& HasPtr::operator =(const HasPtr& rhs){
        ++rhs.ptr->use;//increment use count on rhs first
        if(--ptr->use == 0) //if use count goes to 0 on this object, delete it
            delete ptr;
        ptr = rhs.ptr;//copy the U_ptr
        val = rhs.val;//copy the int member
        return *this;
    }

        下面是原来的HasPtr类

    class HasPtr{
    public:
        //HasPtr owns the pointer, p must been dynamically allocalted
        HasPtr(int *p, int i):ptr(new U_ptr(p)),val(i){}
        //copy memebers and increment the use count
        HasPtr(const HasPtr& orig):
            ptr(orig.ptr),val(orig.val){ ++ptr->use;}
        HasPtr& operator=(const HasPtr&);
        //if use count goes zero, delete th U_ptr object
        ~HasPtr(){
            if (--ptr->use == 0)
                delete ptr;
        }
    
        int *get_ptr()const{return ptr->ip;}
        int get_int()const{return val;}
        
        void set_ptr(int *p){ptr->ip = p;}
        void set_int(int i){val = i;}
    
        int get_ptr_val()const{return *ptr->ip;}
        void set_ptr_val(int val){*ptr->ip = i;}
    private:
        U_ptr* ptr;
        int val;
    };

    复制操作比复制构造函数要复杂点,一般现将右操作数引用计数加1, 然后左操作数对象引用计数减1并检查这个引用计数。

    HasPtr& HasPtr::operator =(const HasPtr& rhs){
        ++rhs.ptr->use;//increment use count on rhs first
        if(--ptr->use == 0) //if use count goes to 0 on this object, delete it
            delete ptr;
        ptr = rhs.ptr;//copy the U_ptr
        val = rhs.val;//copy the int member
        return *this;
    }

    注解: 这个赋值操作符在减少左操作数的使用计数之前使rhs的使用计数加1,从而防止自身赋值。

    现在需要改变访问int*的其他成员,以便通过U_ptr指针简洁获取int

    定义值类型:

      处理指针成员的另一种完全不同的方法,是给指针成员提供值语义(value semantics), 复制值对象时,会得到一个不同的新副本。对副本的操作不会反映到原有对象上,反之亦然。

    代码示例如下:

    #ifndef VALUE_PTR_H
    #define VALUE_PTR_H
    
    class HasPtr{
    public:
        HasPtr(const int&p, int i):ptr(new int(p)),val(i){}
        HasPtr(const HasPtr& orig):ptr(new int(*orig.ptr)),val(orig.val){}
        HasPtr& operator=(const HasPtr&);
        ~HasPtr(){delete ptr;}
    
        int get_ptr_val()const{return *ptr;}
        int get_int()const{return val;}
    
        void set_ptr(int* p){ptr = p;}
        void set_int(int i){val = i;}
    
        int* get_ptr()const{return ptr;}
        void set_ptr_val(int val){*ptr = val;}
    private:
        int* ptr;
        int val;
    };
    
    HasPtr& HasPtr::operator =(const HasPtr& rhs){
        *ptr = *rhs.ptr; //copy the value pointer to
        val = rhs.val;   //copy the int
        return *this;
    }
    #endif // !VALUE_PTR_H

    注解: 即使要讲一个对象赋值给它本身,赋值操作符也必须总是保证正确。 本例中,即使左右操作数相同,操作本质上也是安全的,因此,不需要显示检查自身赋值。

  • 相关阅读:
    LeetCode 116. 填充每个节点的下一个右侧节点指针
    angluar 表单的验证 动态数据项表单验证
    Angular:ng-style,ng-class的使用
    1.splice(),slice(),split()快查
    js输入小写金额转大写
    Angular--CheckBox,checkbox多选,保存的时候用逗号隔开
    Angular--CheckBox
    Angular--Radio
    对于mysql中的group by分组后获取组内创建时间最大的那行数据
    GIT版本管理看这一篇就够了
  • 原文地址:https://www.cnblogs.com/jackStudy/p/4361420.html
Copyright © 2011-2022 走看看