避免指针成员重复释放

类中有指针成员时,如何避免重复释放

在下面的代码中,类A保存有1个指针,并且理所当然的在构造函数中分配内存,析构中释放内存,但会发生重复释放的问题。
原因:编译器自动生成如下的拷贝构造(析构函数不影响拷贝操作的自动生成,只会影响移动操作的自动生成)
解决方法1:显式的删除拷贝构造函数,然后使用时传引用

#include <iostream>
using namespace std;
struct A
{
    A(){
        cout<<"默认构造"<<endl;
        p = malloc(1);
    }
    //A(const A& that):p(that.p){
    //    cout<<"拷贝构造"<<endl;
    //}
    ~A(){
        free(p);
        cout<<"析构"<<endl;
    }
    void *p;
};
int main(int argc, char *argv[])
{
    A a;//默认构造 a.p = malloc(1)
    A b(a);//拷贝构造 b.p = a.p
    //析构 free(b.p)
    //析构 free(a.p)
    return 0;
}

定义了移动构造,就记得析构函数里自己判空

A(A&& that){
 	p = that.p;
    that.p = nullptr;
    cout<<"移动"<<endl;
}
~A(){
    if (p)
    {
        free(p);
        cout<<"析构"<<endl;
    }
}
  • 解决方法2:
    拷贝构造和移动构造函数都删除掉,传参的时候用unique_pointer包装一下,因为独占指针是可以移动的。此时指针指向的资源不可移动,指针可以移动

    #include <iostream>
    #include <memory>
    
    using namespace std;
    
    struct A
    {
        A(){
            p = malloc(1);
        }
        A(const A& that) = delete;
        A(A&& that) = delete;
        ~A(){
            free(p);
        }
        void *p;
    };
    
    void fun(std::unique_ptr<A> x){
    }
    
    int main(int argc, char *argv[])
    {
        auto a_p = make_unique<A>();
        fun(move(a_p));
        return 0;
    }
    
  • 区分

    A a1;
    A a2 = a1;//拷贝构造
    a1 = a2;//拷贝赋值
    
  • 解决方法3:
    实际上只需要删除移动构造,就会默认不生成 移动赋值、拷贝构造、拷贝赋值

    因为:移动构造和移动赋值相互影响 移动操作和拷贝操作相互影响
    同理,只需要删除移动赋值,其余3个也就不会生成了

    A(const A& that) = delete;//拷贝构造
    A(A&& that) = delete;//移动构造
    A &operator=(A && that) = delete;//移动赋值
    A &operator=(const A& that) = delete;//拷贝赋值
    
  • 解决方法4
    把该类写在类中,使用智能指针来管理。当然也可以不写在类中

    #include <iostream>
    #include <memory>
    using namespace std;
    struct A
    {
    private:
        struct A_Imp
        {
            A_Imp(){
                p = malloc(1);
                cout<<"malloc"<<endl;
            }
            ~A_Imp(){
                free(p);
                cout<<"free"<<endl;
            }
            void otherfun(){
                cout<<"xxxx"<<endl;
            }
            void* p; 
        };
        shared_ptr<A_Imp> impl;
    public:
        A(){
            impl = make_shared<A_Imp>();
        }
        A_Imp* operator->(){
            return impl.get();
        }
    };
    
    int main(int argc, char *argv[])
    {
        A a1;
        A a2(a1);
        a1->otherfun();
        return 0;
    }
    
  • 智能指针的深拷贝怎么写

    对智能指针取*然后重新构造一个

    A(const A &that){
        impl = make_shared<A_Imp>(*that.impl);
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值