c++万能但释放内存时痛苦的void *指针及替代方案

void *在c/c++中可以说是万金油的存在,无论什么类型的数据都可以塞给它,但是释放的时候,却需要知道具体的类型,才能调用delete去释放,直接delete void *的指针是未定义的有可能会导致内存泄露。

如果编译器支持c++17, 可用std::any来代替void *, 如果编译器只支持c++ 11可以用shared_ptr来替代。下面以shared_ptr来做为例子

释放void *要知道原来申请的对象是什么类型,伪代码如下:

void *p = new xx;

if p is A:

     delete (A *)p;

else if p is int

     delete (int *)p

else ....

替换成shared_ptr如下

std::shared_ptr<xx> p = std::make_shared<A>(xx);

就一行,不需要手动去释放,生命周期到了,会自动释放内存。

 

具体c++代码如下,其中有注释

#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <memory>

using namespace std;

class Base
{
public:
    Base();
    virtual ~Base();
};

Base::Base()
{
    std::cout << __func__ << std::endl;
}

Base::~Base()
{
    std::cout << __func__ << std::endl;
}

class A : public Base
{
public:
    A(char c);
    virtual ~A();

    char m_c;
};

A::A(char c)
    :m_c(c)
{
    std::cout << __func__ << std::endl;
}

A::~A()
{
    std::cout << __func__ << std::endl;
}

int main(int argc, char **argv)
{
    std::cout << "1-----" << std::endl;
    std::shared_ptr<void> data = std::make_shared<Base>();
    std::cout << "1-----" << std::endl;
    data = std::make_shared<int>(1);
    std::cout << "1-----" << std::endl;

    std::cout << std::endl << "2--------" << std::endl;
    std::shared_ptr<void> dataA = std::make_shared<A>('a');
    std::cout << "2--------c:" << (reinterpret_cast< A* >(dataA.get()))->m_c << std::endl;
    dataA = std::make_shared<std::string>("OK"); // 重新赋值dataA时,原先的内存会被自动释放, 这里会先调用A的析构函数
    std::cout << "2--------" << std::endl;

    std::cout << std::endl << "int------" << std::endl;
    std::shared_ptr<int> dataB = std::make_shared<int>(100);
    std::cout << "int------:" << *dataB << std::endl;

    // 直接delete void *的指针,有可能会内存泄露的
    std::cout << std::endl << "void *------" << std::endl;
    long n = 10;
    void *dataC = (void *)n; // 这里没有分配动态内存空间,所以后面
    std::cout << "n:" << long(dataC) << std::endl;
    dataC = new A('c');
    if (dataC)
    {
        delete dataC; // deleting ‘void*’ is undefined
        dataC = NULL;
    }
    std::cout << "void *------" << std::endl << std::endl;
    
    return 0;
}

编译后运行,输出

1-----
Base
1-----
~Base    //使用shared_ptr这里自动释放
1-----

2--------
Base
A
2--------c:a
~A
~Base   //使用shared_ptr这里自动释放
2--------

int------
int------:100

void *------
n:10
Base
A
void *------  // 使用delete void *的方式,这里A申请内存后结束生命周期时,没有调用析构函数进行内存释放。
作者:帅得不敢出门

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值