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

初始化

#include                                                              
#include                                                              
#include                                                              
using namespace std;                                                            
                                                                                                                                                                                                                                                                              
class Person {                                                                  
public:                                                                         
                                                                                
        Person() {                                                              
                cout <<"Pserson()"<()                                                       
        {                                                                          
                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)"<()                                                       
        {                                                                          
                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"<

说明:

  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)”< 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)"<

改进4: 引入计数

问题:二次删除指针。


 43         ~sp()                                                                   
 44         {                                                                       
 45                 cout<<"~sp()"<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"<

C++基础知识-之智能指针和轻量级指针(韦东山视频学习)_第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()"<incStrong();                                                 
 51         }                                                                       
 52                                                                                 
 53         ~sp()                                                                   
 54         {                                                                       
 55                 cout<<"~sp()"<decStrong();                                         
 60                         //cout<<"~sp() delete1"<getStrongCount<

改进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()"<

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

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

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

count操作原子化

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

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

163 template                                                                                        
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(this);                                                          
174         }                                                                                                                                                               
175     } 

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

你可能感兴趣的:(C++)