C++基础知识-之智能指针和轻量级指针(韦东山视频学习)

初始化

#include <iostream>                                                             
#include <string.h>                                                             
#include <unistd.h>                                                             
using namespace std;                                                            
                                                                                                                                                                                                                                                                              
class Person {                                                                  
public:                                                                         
                                                                                
        Person() {                                                              
                cout <<"Pserson()"<<endl;                                          
        }                                                                          
        ~Person()                                                                  
        {                                                                          
                cout << "~Person()"<<endl;                                         
        }                                                                          
        void printInfo(void)                                                       
        {                                                                          
                cout<<"just a test function"<<endl;                                
        }                                                                          
}

class sp {                                                                         
private:                                                                           
        Person *p=NULL;                                                            
public:                                                                            
        sp() : p(0) {}                                                             
        sp(Person *other)                                                          
        {                                                                          
                cout<<"sp(const Person *other)"<<endl;                             
                p = other;                                                         
        }                                                                          
        sp(int i)                                                                  
        {                                                                          
                cout<<"sp(int="<<i<<")"<<endl;                                     
        }                                                                          
        ~sp()                                                                      
        {                                                                          
                cout<<"~sp()"<<endl;                                               
                if (p)                                                             
                        delete p;                                                  
        }                                                                          
        Person *operator->()                                                       
        {                                                                          
                return p;                                                          
        }                                                                          
                                                                                   
};
void test_func(void)                                                            
{                                                                               
        sp i1(5);                                                               
        sp i2 = 6;                                                              
        sp s = new Person();                                                    
        sp s3(new Person) ;        
        s3->printInfo();
                                                     
                                                                                
}                                                                               
                                                                                
int main(int argc, char **argv)                                                 
{                                                                               
        test_func();                                                            
        return 0;                                                               
} 

初始化变量两种方法:

第一种方法:

class sp;
int k=2;
sp i1(k);   //定义sp对象i1,并传入int类型,初始化参数,将调用 sp(int i)  。

第二种方法:
sp i2 = k;  ///定义sp对象i2,并传入int类型的k变量,初始化参数,将调用 sp(int i)  。

说明:

  1. 使用右值传参法,调用对象的对应析构函数来构造对象。

sp s3(new Person) ;
s3->printInfo();
s3中没有printInfo函数,但是sp对象重载了->符号,返回了sp中person类型的私有数据p的指针tmp,指针再调用printInfo函数。

2. 问题推导

void test_func(void)                                                               
{                                                                                  
        Person *p = new Person();                                                  
        per.printInfo();                                                                                                                                                    
}                                                                                  
                                                                                   
int main(int argc, char **argv)                                                    
{                                                                                  
        int i;                                                                     
                                                                                   
        for (i = 0; i < 2; i++)                                                    
                test_func();                                                       
        return 0;                                                                  
} 

在 test_func中,使用new Person开辟的内存,没有释放,没有执行Person类的析构函数。

改进1: 使用局部变量

在test_func中,使用局部变量,执行Person类的析构函数。

void test_func(void)                                                               
{                                                                                  
        Person per;                                                     
        per.printInfo();                                                                                                                                                    
}                                                                                  
                                                                                   
int main(int argc, char **argv)                                                    
{                                                                                  
        int i;                                                                     
                                                                                   
        for (i = 0; i < 2; i++)                                                    
                test_func();                                                       
        return 0;                                                                  
} 

改进2:在一个类中包含另外一个类指针,在执行这个类析构函数,删除另外一个类指针。

如果
如果函数test_func,是person类指针,则可以在函数test_func申请一个sp类变量A,在sp类中包含person类指针,在释放sp类的析构函数中,如果sp类中的person类指针被赋值,则删除person类指针指向的内存。

class sp {                                                                         
private:                                                                           
        Person *p;                                                                 
                                                                                                                                                                            
public:                                                                            
        sp() : p(0) {}                                                             
                                                                                   
        sp(Person *other)                                                          
        {                                                                          
                cout<<"sp(const Person *other)"<<endl;                             
                p = other;                                                         
        }                                                                          
                                                                                   
        sp(sp &other)                                                              
        {                                                                          
                cout<<"sp(const Person *other)"<<endl;                             
                p = other.p;                                                       
        }                                                                          
                                                                                   
        ~sp()                                                                      
        {                                                                          
                cout<<"~sp()"<<endl;                                               
                if (p)                                                             
                        delete p;                                                  
        }                                                                          
                                                                                   
        Person *operator->()                                                       
        {                                                                          
                return p;                                                          
        }                                                                          
                                                                                   
};

void test_func(sp &other)                                                       
{                                                                               
        sp s = other;                                                           
                                                                                
        s->printInfo();                                                         
                                                                                                                                                                            
} 

int main(int argc, char **argv)                                                    
{                                                                                  
                                                                                   
        sp other = new Person();                                                   
        test_func(other);                                                          
                                                                                                                                                                            
        cout<<"main() end"<<endl;                                                  
                                                                                   
        return 0;                                                                  
}  

说明:

  1. main函数
    sp other = new Person();==>Person *per1 = new Person(); sp other(per1),声明了一个名为other的sp对象。
    2)test_func函数中
    sp &other1=other;
    sp s = other1; ==>则会调用构造函数
    sp(sp &other)
    {
    cout<<“sp(const Person *other)”<<endl;
    p = other.p;
    }
    sp &other = other1; //引用不能等于临时变量。
    const sp &other = other1;

改进3:类的析构函数的参数使用const sp &修饰

修改3:析构函数修改为const sp &,修改代码如下:

class sp {                                                                                                                                     
                                                                                   
        sp(const sp &other)                                                              
        {                                                                          
                cout<<"sp(const Person *other)"<<endl;                             
                p = other.p;                                                       
        }                                                                          
                                                                                   
}

改进4: 引入计数

问题:二次删除指针。


 43         ~sp()                                                                   
 44         {                                                                       
 45                 cout<<"~sp()"<<endl;                                            
 46                 if (p)                                                          
 47                 {                                                               
 48                         cout<<"~sp() before delete!"<<endl;                     
 49                         delete p;                                               
 50                         p = NULL;                                               
 51                         cout<<"~sp() after delete!"<<endl;                      
 52                 }                                                               
 53         }  

 62 void test_func(sp &other)                                                       
 63 {                                                                               
 64         sp s = other;                                                                                                             
 66         s->printInfo();                                                         
 67 }                                                                               
 68                                                                                 
 69 int main(int argc, char **argv)                                                 
 70 {                                                                               
 71                                                                                 
 72         sp other = new Person();                                                                                                                                        
 73         test_func(other);                                                       
 74                                                                                 
 75         cout<<"main() end"<<endl;                                               
 76                                                                                 
 77         return 0;                                                               
 78 }  

1
在test_func执行结束时候,销毁other,执行sp类析构函数,判断p不为空,则delete p指向的p1;在main函数执行结束后,销毁s1,显然p=123456,不为空,再次销毁p,会产生错误。

解决思路:引入计数,当是最后一个使用者,销毁p。

解决程序如下:

  8 class Person {                                                                  
  9 private:                                                                        
 10         int count;                                                              
 11                                                                                 
 12 public:                                                                         
 13         void incStrong(){ count++; }                                            
 14         void decStrong(){ count--; }                                            
 15         int getStrongCount(){ return count;}                                    
 16                                                                                 
 17         Person() : count(0){                                                    
 18                 cout <<"Pserson()"<<endl;                                       
 19         }                                                                       
 20                                                                                 
 21                                                                                 
 22         ~Person()                                                               
 23         {                                                                       
 24                 cout << "~Person()"<<endl;                                      
 25         }                                                                       
 26         void printInfo(void)                                                    
 27         {                                                                       
 28                 cout<<"just a test function"<<endl;                             
 29         }                                                                       
 30 }; 

 46         sp(const sp &other)                                                     
 47         {                                                                       
 48                 cout<<"sp(const sp &other)"<<endl;                              
 49                 p = other.p;                                                    
 50                 p->incStrong();                                                 
 51         }                                                                       
 52                                                                                 
 53         ~sp()                                                                   
 54         {                                                                       
 55                 cout<<"~sp()"<<endl;                                            
 56                                                                                 
 57                 if (p)                                                          
 58                 {                                                               
 59                         p->decStrong();                                         
 60                         //cout<<"~sp() delete1"<<p->getStrongCount<<endl;       
 61                         cout<<"~sp() cout="<<p->getStrongCount()<<endl;         
 62                         if (p->getStrongCount() == 0)                           
 63                         {                                                       
 64                                 cout<<"~sp() delete"<<endl;                     
 65                                 delete p;                                       
 66                                 p = NULL;                                       
 67                         }                                                       
 68                 }                                                                                                                                                       
 69         }  

改进5:计数count封装成一个类

计数count很多类中都用,把count封装成一个基类。

class RefBase {                                                                                                                                                             
private:                                                                           
        int count;                                                                 
                                                                                   
public:                                                                            
        RefBase() : count(0) {}                                                    
        void incStrong(){ count++; }                                               
        void decStrong(){ count--; }                                               
        int getStrongCount(){ return count;}                                       
};                                                                                 
class Person : public RefBase{                                                     
public:                                                                            
        Person() {                                                                 
                cout <<"Pserson()"<<endl;                                          
        }                                                                          
                                                                                   
                                                                                   
        ~Person()                                                                  
        {                                                                          
                cout << "~Person()"<<endl;                                         
        }                                                                          
        void printInfo(void)                                                       
        {                                                                          
                cout<<"just a test function"<<endl;                                
        }                                                                          
}; 

改进6: 在SP类中,引入模板

有用信息是,SP类属性P指针,P既可以是person类,也可以是其他类。把SP类做成模板。代码如下:

template<typename T>                                                            
class sp {                                                                      
private:                                                                        
        T *p;                                                                   
public:                                                                         
        sp() : p(0) {}                                                          
        sp(T *other)                                                            
        {                                                                       
                cout<<"sp(T *other)"<<endl;                                     
                p = other;                                                      
                p->incStrong();                                                 
        }                                                                       
        sp(const sp &other)                                                     
        {                                                                       
                cout<<"sp(const sp &other)"<<endl;                              
                p = other.p;                                                    
                p->incStrong();                                                 
        }                                                                       
        ~sp()                                                                   
        {                                                                       
                cout<<"~sp()"<<endl;                                            
                                                                                
                if (p)                                                          
                {                                                               
                        p->decStrong();                                         
                        if (p->getStrongCount() == 0)                           
                        {                                                       
                                delete p;                                       
                                p = NULL;                                                                                                                                   
                        }                                                       
                }                                                               
        }     
        T *operator->()                                                         
        {                                                                       
                return p;                                                       
        }                                                                       
                                                                                
        T& operator*()                                                          
        {                                                                       
                return *p;                                                      
        }                                                                       
                                                                                
};      

count操作原子化

在这里插入图片描述

如图所示,两个线程操作cout,如果在A线程的count还没写进内存,B线程从内存取的count不是A线程增加过的,就会导致count=2,而不是3.解决办法,最count进行原子操作。

163 template <class T>                                                                                       
164 class LightRefBase                                                                                       
165 {                                                                                                        
166 public:                                                                                                  
167     inline LightRefBase() : mCount(0) { }                                                                
168     inline void incStrong(__attribute__((unused)) const void* id) const {       
169         __sync_fetch_and_add(&mCount, 1);                                                                
170     }                                                                                                    
171     inline void decStrong(__attribute__((unused)) const void* id) const {       
172         if (__sync_fetch_and_sub(&mCount, 1) == 1) {                                                     
173             delete static_cast<const T*>(this);                                                          
174         }                                                                                                                                                               
175     } 

在Android引入,__sync_fetch_and_add(&mCount, 1)对count进行原子操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值