跟着动手,泛型编程从未如此简单3

跟着动手,知行泛型编程

实现一个“真正”的泛型Stack

接着上一章的内容继续,上一张章节我们实现类一个“伪泛型”Stack, 它支持c/c++内置类型,如float,double,short等,自定义的类型,入栈数据本身进行了内存开辟等,则显得力不从心,发生了内存泄漏,如:

    char* stringNames[] = {"ali","bob","peter"};
    //push
    for(int i = 0; i < 3; i++){
        char* copy = strdup(stringNames[i]);//strdup内部会调用malloc开辟内存,需要调用free
        stackObj.GenericStackPush(&copy);
    }
    //pop
    char* name;
    for(int i = 0; i < 1; i++){//出栈一次,只释放类最后一个数据开辟的内存空间
        stackObj.GenericStackPop(&name);
        printf("pop: %s\n",name);
        free(name);
    }

对于上述代码,入栈、出栈次数不想等,则会造成内存泄漏!如何解决该问题?

关键点

  • 自定义freeFun,该freeFun作为参数传入构造函数
  • 析构函数判断Stack当前栈长度并进行自动析构

实现

  • GenericStack.h定义
class GenericStack{
    public:
        int m_nLogicLen;
        int m_nAssignLen;
        void* m_pElementBuffer;
        int m_nElementSize;
        void (*m_fFreeFun)(void*);//新增:函数指针,用于释放入栈时产生的内存拷贝
    public:
        GenericStack(int elementSize, void (*FreeFun)(void*));//新增FreeFun参数
        ~GenericStack();
    public:
        bool GenericStackPush(void* elementBuffer);
        bool GenericStackPop(void* elementBuffer);
    private:
        bool GenericStackGrow();
};
  • GenericStack.cpp 新增成员函数实现
/*
* @brief 构造函数
* @elementSize 栈中存放的元素的字节长度
* @FreeFun 函数指针,自定义的freeFun函数
*/
GenericStack::GenericStack(int elementSize,void (*FreeFun)(void*)){
    this->m_nLogicLen = 0;
    this->m_nAssignLen = 4;
    this->m_nElementSize = elementSize;
    this->m_pElementBuffer = malloc(this->m_nAssignLen * this->m_nElementSize);
    this->m_fFreeFun = FreeFun;                  //新增
    assert(this->m_pElementBuffer != NULL);
}
/*
* @brief 析构函数,析构时自动判断队列是否为空,不为空调用型自定义freeFun进行内存释放
*/
GenericStack::~GenericStack(){
    if( this->m_fFreeFun != NULL){             //当用户自定义freeFun时进入
        for(int i = 0; i < this->m_nLogicLen; i++){
            char* address = (char*)this->m_pElementBuffer + i * this->m_nElementSize;
            this->m_fFreeFun(address);
        }
    }
    free(this->m_pElementBuffer);
}
  • 调用示范
//自定义的freeFun
void StringFree(void* vp){
    char* address = *(char**)vp;
    printf("free string: %s\n",address);
    free( address );
}
int main(){
    GenericStack stackObj(sizeof(char*), StringFree);    //传入自定义freeFun
    char* stringNames[] = {"ali","bob","peter"};
    //push
    for(int i = 0; i < 3; i++){
        char* copy = strdup(stringNames[i]);//strdup内部会调用malloc开辟内存,所以要调用free,这样来模拟需要申请内存空间的stack对象
        stackObj.GenericStackPush(&copy);
    }
    //pop
    char* name;
    for(int i = 0; i < 1; i++){//以上使用了malloc这里要对应free
        stackObj.GenericStackPop(&name);
        printf("pop: %s\n",name);
        free(name);
    }
    return 1;
}

该程序运行完成后,析构函数会调用两次StringFree函数,用于释放入栈所申请的内存空间,这样一个真正意义上的泛型Stack就实现完成了!
到此,整个泛型Stack章节到此就结束了,欢迎小伙伴么多多交流!
推荐一首歌曲, 林志炫大叔,我是歌手我最喜欢的一首歌:没离开过

border="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=25714355&auto=1&height=66">
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值