避免指针成员重复释放

2024-06-19 14:20

本文主要是介绍避免指针成员重复释放,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

在下面的代码中,类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);
    }
    

这篇关于避免指针成员重复释放的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1075272

相关文章

C语言入门系列:探秘二级指针与多级指针的奇妙世界

文章目录 一,指针的回忆杀1,指针的概念2,指针的声明和赋值3,指针的使用3.1 直接给指针变量赋值3.2 通过*运算符读写指针指向的内存3.2.1 读3.2.2 写 二,二级指针详解1,定义2,示例说明3,二级指针与一级指针、普通变量的关系3.1,与一级指针的关系3.2,与普通变量的关系,示例说明 4,二级指针的常见用途5,二级指针扩展到多级指针 小结 C语言的学习之旅中,二级

LeetCode--220 存在重复元素 III

题目 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。 示例 示例 1:输入: nums = [1,2,3,1], k = 3, t = 0输出: true示例 2:输入: nums = [1,0,1,1], k = 1, t = 2输出: true示例

LeetCode--217 存在重复元素

题目 给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。 示例 示例 1:输入: [1,2,3,1]输出: true示例 2:输入: [1,2,3,4]输出: false示例 3:输入: [1,1,1,3,3,4,3,2,4,2]输出: true class Solution {p

axios全局封装AbortController取消重复请求

为什么? 问题:为什么axios要配置AbortController?防抖节流不行吗? 分析: 防抖节流本质上是用延时器来操作请求的。防抖是判断延时器是否存在,如果存在,清除延时器,重新开启一个延时器,只执行最后一次请求。节流呢,是判断延时器是否存在,如果存在,直接return掉,直到执行完这个延时器。事实上,这些体验感都不算友好,因为对于用户来说,得等一些时间,尤其是首次请求,不是那么流畅

利用结构体作为函数参数时结构体指针的定义

在利用结构体作为函数的参数进行传递时,容易犯的一个错误是将一个野指针传给函数导致错误。 #include <stdio.h>#include <math.h>#include <malloc.h>#define MAXSIZE 10typedef struct {int r[MAXSIZE]; //用于存储要排序的数组,r[0]作为哨兵或者临时变量int length;

isa指针的理解

D3实例isa指向D3类对象。D3类的话isa指向D3元类对象。D3元类保存类中的方法调度列表,包括类方法和对象方法

Netty ByteBuf 释放详解:内存管理与最佳实践

Netty ByteBuf 释放详解:内存管理与最佳实践 在Netty中(学习netty请参考:🔗深入浅出Netty:高性能网络应用框架的原理与实践),管理ByteBuf的内存是至关重要的(学习ByteBuf请参考:🔗Netty ByteBuf 详解:高性能数据缓冲区的全面介绍)。未能正确释放ByteBuf可能会导致内存泄漏,进而影响应用的性能和稳定性。本文将详细介绍如何正确地释放ByteB

C/C++语言基础知识 之 引用和指针

关于引用 引入是C++引入的新语言特性。 1 int &rn = a;-----------------------------------------------2 int* p = &a;3 int* &pa = p;4 (*pa)++;5 pa = &b;6 (*pa)++; L1:声明rn为变量a的一个引用,不需要为rn另外开辟内存单元。rn和a占

leetcode刷题(40)——83. 删除排序链表中的重复元素

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。 示例 1: 输入: 1->1->2 输出: 1->2 示例 2: 输入: 1->1->2->3->3 输出: 1->2->3 平时我们删除一个链表中的某个元素,一般都是以下的写法: temp.next = temp.next.next; 这样temp.next就被删除了 此题解法如下: class Solution

leetcode刷题(98)——652. 寻找重复的子树

给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。 两棵树重复是指它们具有相同的结构以及相同的结点值。 示例 1: 1/ \2 3/ / \4 2 4/4 下面是两个重复的子树: 2/4 和 4 因此,你需要以列表的形式返回上述重复子树的根结点。 /*** Definition for a binar