Symbian 智能指针

Symbian 智能指针
在Symbian开发过程中, 由于没有确定性析构, 最让人烦躁的就是Cleanup Stack的操作, 当在一个函数中使用局部变量时,
要记得PushL, 然后在函数末尾, 还要PopAndDestroy, 变量一多, 头昏脑胀,都找不到北了, 经常被Panic, 而且在VC6窗口
中还不知道到底是哪行的问题, 只能单步调试, 一直到程序crash. 然后知道上一行就是问题所在.

下面是我写的一个智能指针类( 实际上是两个, 一个CPtr用于C class, 一个RPtr 用于R class), 我自己的使用经验表明可以免除90%的对Cleanup Stack的操作. (实际上我在新代码中从来不再手动使用CleanupStack了)

例如一个简单的代码:
void FunL()
{
   HBufC * wbuf = HBufC::NewL(10);
   CleanupStack::PushL(wbuf); //有点造作, 应该直接的用HBufC::NewLC, 仅仅是举个例子, 因为很多类只提供了NewL


   HBufC * wbuf2 = HBufC::NewL(20);
   CleanupStack::PushL(wbuf2);

   RFs fs;
   User::LeaveIfEror( fs.Connect());
   CleanupClosePushL(fs);


   do_sth_maybe_leaveLLL();

   CleanupStack::PopAndDestroy(3);    //关文件fs, 删除wbuf, wbuf2
}


如果函数中又增加一个C对象的使用, 那么要手动PushL一次, 然后在结尾还要记得将PopAndDestroy(3) 改为 4.

如果利用智能指针, 上面的代码可以简化为:

void FunL()
{
   using namespace sbl;                   //封装在sbl中

   CPtr<HBufC> wbuf(HBufC::NewL(10));    //永远不要调用NewLC, CPtr内部会PushL的
   CPtr<HBufC> wbuf2(HBufC::NewL(20));   //同上

   RPtr<RFs> fs;
   User::LeaveIfEror( fs->Connect());   //fs.Connect() 改为 fs->Connect()

   do_sth_maybe_leaveLLL();            
}

以后就什么都不用管了, Leave也好, 不Leave也好, wbuf, wbuf2最终都会被delete, fs都会被关闭.

记住的是:
1. 不要对成员变量使用CPtr, RPtr (你应该知道, 成员变量本身就不应该PushL)
2. 在一个函数中不要混合使用CleanupStack 和 智能指针类. 要不你就手动的PushL, 要不就全部交给智能指针.
3. 在给CPtr智能指针初始化/赋值的时候, 永远不要调用Cxxx::NewLC, (因为NewLC自己PushL一次了), 而总是调用NewL.

另外, 有了智能指针, 基本上你无需再给你的class提供NewLC了, 而且NewL中的实现可以如下:

/* static */
CFoo * CFoo::NewL()
{
   CPtr<CFoo> self( new (ELeave)CFoo);  //放心, CPtr内部已经PushL了, 保护了这个self
   self->ConstructL();                  //Leave也无问题, 会调用delete self的.
   return self.release();               //release 释放所有权, 这样CPtr析构的时候不会再去delete self.
}


基本上, 你了解STL中的auto_ptr, 也就了解了CPtr. RPtr有点不同, 主要用于使用R class, 它内部放的不是T*,而是直接T本身.

再举个CPtr的例子:

void foo()
{
    CPtr<HBufC> wbuf(HBufC::NewL(20));   //分配内存
    *wbuf = _L("Hello,world");           //给 HBufC 赋值
    wbuf = 0;                            //释放, 注意HBufC已经释放了, 或者 reset(0)也可以
  
   
   wbuf = HBufC::NewL(20);             //又分配内存
   wbuf = HBufC::NewL(40);             //哎呀, 不够, 释放刚刚分配的, 分配一块大的内存
   *wbuf = _L("long long long hello, world ");
}

基本上和stl中的auto_ptr使用没有什么分别. 不过由于symbian的cleanup机制, 不能将CPtr/RPtr作为成员变量.


下面是源代码: (使用的时候别忘了CPtr, RPtr都是在sbl namespace中, 另外, debug版本中用到了c library的assert)


#include <e32base.h>

#include <libc/assert.h>

#include <libc/string.h>


namespace sbl  //sbl stands for SymBian Library
{
// a auto_ptr for any object can be free by "delete" operator
// if you know std::auto_ptr then no much thing you need to study
template<class T>
class CPtr
{
public:
    //take a raw pointer, this pointer must not been pushed into cleanup stack
    explicit CPtr(T* ptr = 0) : ptr_(ptr)
    {
        //no matter how we need a slot in cleanup stack
        CleanupPushL();
    }

    //copy ctor, take ownership, just like std::auto_ptr
    CPtr(CPtr<T>& other)
    {
        ptr_ = other.release();
        CleanupPushL();
    }

    //assignment, take ownership, just like std::auto_ptr
    CPtr<T>& operator=(CPtr<T>& other)
    {
        if(this != &other) {
            assert( ptr_ != other.ptr_);
            reset(other.release());
        }
        return *this;
    }
   
    CPtr<T>& operator=(T* ptr)
    {
        reset(ptr);
        return *this;
    }
   
    /* sorry, due to buggy vc6
     template<class U>
     CPtr(CPtr<U>& other)
     {
     CleanupPushL();
     ptr_ = other.release();
     }

     template<class U>
     CPtr<T>& operator=(CPtr<U>& other)
     {
     reset(other.release());
     reutrn *this;
     }
     */   
    T& operator*() const
    {
        assert(ptr_ != 0);
        return *ptr_;
    }
   
    T* operator->() const
    {
        assert(ptr_ != 0);
        return ptr_;
    }
   
    // get the raw pointer explicitly
    T* get() const
    {
        return ptr_;
    }
   
    void reset(T* ptr = 0)
    {
        if(ptr != ptr_)
        {
            delete ptr_;        // here we use "delete" to free resource
            ptr_ = ptr;
        }
    }

    // release ownership
    T* release()
    {
        T* tmp = ptr_;
        ptr_ = 0;
        return tmp;
    }

    //normally exit, dispose
    ~CPtr()
    {
        CleanupStack::PopAndDestroy(1, this); // remove from cleanup stack
    }

    typedef void (*safe_bool)(void *p);

    // used by if (c)
    operator safe_bool() const
    {
        return ptr_ ? &Dispose : 0;
    }

    //used by if(!c)
    bool operator!() const
    {
        return safe_bool(*this) == 0;
    }

private:
    T* ptr_;
   
    void CleanupPushL()
    {
        CleanupStack::PushL(TCleanupItem(OnLeave, this));
    }
   
    static void OnLeave(void * p);
};

//this function isn't inline since cleanup stack want our function pointer
template<class T>
void CPtr<T>::OnLeave(void * p)
{
    CPtr * cptr = static_cast<CPtr*>(p);
    cptr->reset(0);
}

//default R class uses Close() to release resource
template<class R>
class RTrait
{
public:
    static void Dispose(R& r)
    {
        r.Close();
    }
    static bool Connected(const R& r);
};

// default R class check binary bits to determine if connected
template<class R>
bool RTrait<R>::Connected(const R& r)
{
    const char * start = (const char *)&r;
    const char * end =  start + sizeof(R);
       
    for(; start != end; start++)
    {
        if ( *start != 0)
            return true;
    }
    return false;
}

   
template<class R, class Trait = RTrait<R> >
class RPtr
{
public:
    RPtr()
    {
        assert(!Trait::Connected(res_));
        CleanupStack::PushL(TCleanupItem( OnLeave, this));
    }

    template<class A1>
    RPtr(const A1& a) : res_(a)
    {
        CleanupStack::PushL(TCleanupItem( OnLeave, this));
    }

    /*
     template<class A1, class A2>
     RPtr(const A1& a1, const A2& a2) : res_(a1, a2)
     {
     CleanupStack::PushL(TCleanupItem( DisposeInvoker, this));
     }

     template<class A1, class A2, class A3>
     RPtr(const A1& a1, const A2& a2, const A3& a3) : res_(a1, a2, a3)
     {
     CleanupStack::PushL(TCleanupItem( DisposeInvoker, this));
     }
     */
       
    ~RPtr()
    {
        CleanupStack::PopAndDestroy(1, this); // remove from  cleanup stack and delete
    }
   
    R* operator->()
    {
        return &res_;
    }

    R& operator*()
    {
        return res_;
    }

   
    R& get()
    {
        return res_;
    }
   
    operator R& ()
    {
        assert( safe_bool(*this));
        return res_;
    }
   
    typedef void (*safe_bool)(void*);
    // used by if(r)
    operator safe_bool() const
    {
        return Trait::Connected(res_) ? &OnLeave : 0;
    }

    //used by if(!r)
    bool operator!() const
    {
        return safe_bool(*this) == 0;
    }
   
private:
    R res_;

    static void OnLeave(void * p);

    //noncopyable and assignable
    RPtr&  operator=(const RPtr&);
    RPtr(const RPtr&);
};

template<class R, class Trait>
void RPtr<R, Trait>::OnLeave(void * p)
{
    RPtr<R, Trait>* self = static_cast< RPtr<R, Trait>*>(p);

    // if(*self) to check if the R class is connected
    if(*self) {
        Trait::Dispose(self->res_);
        assert(!Trait::Connected(self->res_));
    }
}

}  //end of namespace

#endif
 

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值