不改原始类结构,不改变原始函数调用,加上有引用计数的智能指针

智能指针是管家,原始指针是野马 std::unique_ptr 是 C++11 引入的一个智能指针类,它是一个 独占性所有权 的智能指针,意味着它总是唯一拥有指针所指向的对象。C++11引入了三种智能指针:std::unique_ptr、std::shared_ptr和std::weak_ptr。在 C++14 中,std::make_unique 被引入,它是创建 unique_ptr 的推荐方法。std::weak_ptr不拥有它所指向的对象,主要用于解决shared_ptr之间的循环引用问题。它通常与shared_ptr一起使用。 阅读详情

如果在设计之初没有考虑使用智能指针,有可能在程序所有的地方都是直接使用类的裸指针,在后来再使用智能指针就有可能引入别的问题,大库和函数语义的改变,这样会导致不可知的错误,所以这里尝试提供一个不改变原始类结构的智能指针。


假定现在有类CTestClass, 原来的使用方法是CTestClass * pTClass = new CTestClass(xxxx);

在函数调用中使用CTestClass的指针, 如: HRESULT Process(CTestClass * pClass);


这时我们要在整个设计中使用智能指针,在短平快的指导思想下,不如自己设计一个,一方面可以学习智能指针的思想理论,令一方面还可以直接结合实际,让理论为自己产生价值。


当然,学习首先是拿来,

        在使用了ComPtr之后,发现,虽然ComPtr虽然好用,但是它需要操作的类是继承自IUnknown的,而且每一个这样的类都需要实现IUnknown的3个方法,即使在你不需要QueryInterface的时候也是如此。

       转而使用Chrome开源代码中的 scoped_refptr,这个自然也是需要操作的类继承自RefCounted, 而且还要把Chrome代码中的base拿来用。

    Boost库就不能考虑了。


那么,什么才是合适的设计呢, 如下定义:

1. 短小精干

2. 不改变或尽量少改变已有的接口, 实现中也只能做相对少的修改


在原来的设计中, 大量的使用了如下操作

	1. CTestClass * pClass = new CTestClass(....);
	2. returntype Procedure(..., pClass, ...)
	3. CTestClass * ReturnProcedure(...)
	4. pClass2 = pClass
	5. pClass->xxxxx()


统计一下比较多的操作是

	1. CTestClass * ReturnProcedure(...)
	2. pClass2 = pClass;
	3. pClass->xxxxx();

所以先设计满足条件的测试程序

首先是测试的类

class CTestClass
{
public:
	CTestClass(){ATLTRACE(_T(__FUNCTION__) _T("\n"));}
	virtual ~CTestClass(){ATLTRACE(_T(__FUNCTION__) _T("\n"));}
	void Do(LPCTSTR lpszText){ATLTRACE(_T(__FUNCTION__) _T(" %s\n"), lpszText);}

};

class CTestClass2
{
	int m_nSize;
public:
	CTestClass2(int nSize):m_nSize(nSize){ATLTRACE(_T(__FUNCTION__) _T("\n"));}
	virtual ~CTestClass2(){ATLTRACE(_T(__FUNCTION__) _T(" %d\n"), m_nSize);}
	void Do(LPCTSTR lpszText){ATLTRACE(_T(__FUNCTION__) _T(" %s\n"), lpszText);}

};

然后是测试程序

	CAutoSmartPtr<CTestClass> aspTest;

 	CTestClass * pClass = aspTest;

 	pClass->Do(_T("class test"));
 	CAutoSmartPtr<CTestClass> aspTest2 = aspTest;

 	aspTest2->Do(_T("aspTest2->Do"));

	struct foo
	{
		static void run(CTestClass * ptc, void ** pp)
		{
 			CAutoSmartPtr<CTestClass> ssptc(ptc);
 			ssptc->Do(_T("run"));
 			CAutoSmartPtr<CTestClass2> ss2(1000);
 			ss2.CopyTo(pp);
		}
	};

	CAutoSmartPtr<CTestClass2> asp2;
	foo::run(aspTest2, &asp2);

	CAutoSmartPtr<CTestClass2> aspTest3(300);
	aspTest3->Do(_T("aspTest3->Do"));


因为CTestClass * ReturnProcedure(....) 并不能确定是一个引用类指针的操作(如ReturnProcedure()->xxxx())还是一个把该引用赋值给一个指针,所以,在修改的时候需要观察原程序确定的意义。

智能指针设计如下

template<typename T>
class CAutoSmartPtr
{
	class TFollowClass:public T
	{
	private:
		long m_ref;		
	public:		
		void addref(){m_ref++;}
		void releaseref()
		{
			if(!((--m_ref) > 0)) delete this;
		}

		TFollowClass():m_ref(0){}		
		virtual ~TFollowClass(){}

		template<typename A1>
		TFollowClass(A1 a1):m_ref(0),T((A1)a1){}

		template<typename A1,typename A2>
		TFollowClass(A1 a1, A2 a2):m_ref(0),T((A1)a1,(A2)a2){}

		template<typename A1,typename A2, typename A3>
		TFollowClass(A1 a1, A2 a2, A3 a3):m_ref(0),T((A1)a1,(A2)a2,(A3)a3){}

		template<typename A1,typename A2, typename A3, typename A4>
		TFollowClass(A1 a1, A2 a2, A3 a3):m_ref(0),T((A1)a1,(A2)a2,(A3)a3, (A4)a4){}

		template<typename A1,typename A2, typename A3, typename A4, typename A5>
		TFollowClass(A1 a1, A2 a2, A3 a3):m_ref(0),T((A1)a1,(A2)a2,(A3)a3, a4, a5){}
	};
protected:		

	TFollowClass * pshareptr;		
	void ptrrelease()
	{
		if(pshareptr)	pshareptr->releaseref();
	}
	void ptraddref()
	{
		if(pshareptr)	pshareptr->addref();
	}
public:

	CAutoSmartPtr():pshareptr(NULL){}
	~CAutoSmartPtr(){ptrrelease();}
	CAutoSmartPtr(CAutoSmartPtr & src):pshareptr(src.pshareptr){ptraddref();}

	template<typename A1>
	CAutoSmartPtr(A1 a1)	
	{
		pshareptr = new TFollowClass(a1);
		ptraddref();
	}

	template<typename A1, typename A2>
	CAutoSmartPtr(A1 a1, A2 a2):
	pshareptr(NULL)
	{
		pshareptr = new TFollowClass(a1, a2);
		ptraddref();
	}

	template<typename A1, typename A2, typename A3>
	CAutoSmartPtr(A1 a1, A2 a2, A3 a3):
	pshareptr(NULL)
	{
		pshareptr = new TFollowClass(a1, a2, a3);
		ptraddref();
	}

	template<typename A1, typename A2, typename A3, typename A4>
	CAutoSmartPtr(A1 a1, A2 a2, A3 a3, A4 a4 ):
	pshareptr(NULL)
	{
		pshareptr = new TFollowClass(a1, a2, a3, a4);
		ptraddref();
	}

	template<typename A1, typename A2, typename A3, typename A4, typename A5>
	CAutoSmartPtr(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5):
	pshareptr(NULL)
	{
		pshareptr = new TFollowClass(a1, a2, a3, a4, a5);
		ptraddref();
	}

	CAutoSmartPtr & operator = (CAutoSmartPtr & src)
	{
		ptrrelease(); 
		pshareptr = src.pshareptr; 
		ptraddref();
		return *this;
	}
	CAutoSmartPtr & operator = (void *pSrc)
	{		
		ptrrelease(); 
		pshareptr = static_cast<TFollowClass *>(pSrc); 
		if(pshareptr)
			pshareptr->addref();
		return *this;
	}

	CAutoSmartPtr(T * pSrc):pshareptr(static_cast<TFollowClass *>(pSrc))
	{		
		if(pshareptr)
			pshareptr->addref();
	}
	

	void CopyTo(void ** pp)
	{
		*pp = (void*)pshareptr;

		if(pshareptr)
			pshareptr->addref();
	}
	operator bool ()
	{
		return !!pshareptr->p;
	}
	void ** operator &()
	{		
		ptrrelease();
		return (void**)&pshareptr;
	}
	T& operator * (){return *(static_cast<T*>(pshareptr));}
	operator T*(){return static_cast<T*>(pshareptr);}
	T* operator ->(){return static_cast<T*>(pshareptr);}
	bool operator !(){return (pshareptr == NULL);}
	bool operator <(T*pT){return static_cast<T*>(pshareptr) < pT;}
	bool operator >(T*pT){return static_cast<T*>(pshareptr) > pT;}
	bool operator != (T*pT) {return static_cast<T*>(pshareptr) != pT;}
	bool operator == (T*pT) {return static_cast<T*>(pshareptr) == pT;}
	
};	

注意,因为这个智能指针在初始化的时候生成的是一个继承自原始类的指针,其实方法和让操作类继承自引用计数是一样的,但是这里的表现形式不同,不需要去修改原始类的代码

  • 在所有使用new CTestClass的地方替换成 CAutoSmartPtr<CTestClass>(....),它有和CTestClass一样的初始化列表
  • 在所有给指针赋值的地方都换成CopyTo
    原来的是
      
    CTestClass * pClass = new CTestClass;
    CTestClass * pClass2 = GetPointer();
    CTestClass * GetPointer()
    {
    ...
    return pClass;
    }

    现在是
    CAutoSmartPtr<CTestClass> pClass;
    CAutoSmartPtr<CTestClass> pClass2;
    GetPointer(&pClass2);
    CTestClass * GetPointer(void ** ppClass)
    {
        CAutoSmartPtr<CTestClass> spClass;
        spClass.CopyTo(ppClass); // 这里的引用计数已经被加1了
        return spClass;
    }

    让CAutoSmartPtr接近类的语义的代价就是pClass一开始就是一个CTestClass的实例, 而不像其他的智能指针那样一开始是NULL,必须显示的给他赋值,如:
    xxx::scope_ptr<CTestClass> spClass = new CTestClass,
    所以CAutoSmartPtr的 & 操作会先释放一次原来类的实例

    可以修改一个和其他智能指针一样的语义的实现
    去掉几个的实现
    template<typename A1>
    	CAutoSmartPtr(A1 a1)	
    	{
    		pshareptr = new TFollowClass(a1);
    		ptraddref();
    	}

    // 加上
    static CAutoSmartPtr CreateInstance()  // 无参数的初始化
    {
    	pshareptr = new TFollowClass(a1);
    	ptraddref();
    }
    // 加上几个
    template<typename A1>
    static CAutoSmartPtr CreateInstance(A1 a1) // 参数初始化
    {
    	pshareptr = new TFollowClass(a1);
    	ptraddref();
    }
    

    初始化的时候改成

    CAutoSmartPtr<CTestClass> spClass = CAutoSmartPtr<CTestClass>::CreateInstance(); // 没有参数的情况
    CAutoSmartPtr<CTestClass> spClass = CAutoSmartPtr<CTestClass>::CreateInstance(3); // 1参数的情况 CTestClass(int x)



    完成的程序
    template<typename T>
    class CAutoSmartPtr
    {
    	class TFollowClass:public T
    	{
    	private:
    		long m_ref;		
    	public:		
    		void addref(){m_ref++;}
    		void releaseref()
    		{
    			if(!((--m_ref) > 0)) delete this;
    		}
    
    		TFollowClass():m_ref(0){}		
    		virtual ~TFollowClass(){}
    
    		template<typename A1>
    		TFollowClass(A1 a1):m_ref(0),T((A1)a1){}
    
    		template<typename A1,typename A2>
    		TFollowClass(A1 a1, A2 a2):m_ref(0),T((A1)a1,(A2)a2){}
    
    		template<typename A1,typename A2, typename A3>
    		TFollowClass(A1 a1, A2 a2, A3 a3):m_ref(0),T((A1)a1,(A2)a2,(A3)a3){}
    
    		template<typename A1,typename A2, typename A3, typename A4>
    		TFollowClass(A1 a1, A2 a2, A3 a3):m_ref(0),T((A1)a1,(A2)a2,(A3)a3, (A4)a4){}
    
    		template<typename A1,typename A2, typename A3, typename A4, typename A5>
    		TFollowClass(A1 a1, A2 a2, A3 a3):m_ref(0),T((A1)a1,(A2)a2,(A3)a3, a4, a5){}
    	};
    protected:		
    
    	TFollowClass * pshareptr;		
    	void ptrrelease()
    	{
    		if(pshareptr)	pshareptr->releaseref();
    	}
    	void ptraddref()
    	{
    		if(pshareptr)	pshareptr->addref();
    	}
    	
    public:
    	CAutoSmartPtr():pshareptr(NULL){}
    	~CAutoSmartPtr(){ptrrelease();}
    	CAutoSmartPtr(CAutoSmartPtr & src):pshareptr(src.pshareptr){ptraddref();}
    
    	// 加上
    	static CAutoSmartPtr CreateInstance()  // 无参数的初始化
    	{
    		return CAutoSmartPtr(new TFollowClass);		
    	}
    	// 加上几个
    	template<typename A1>
    	static CAutoSmartPtr CreateInstance(A1 a1) // 参数初始化
    	{
    		return CAutoSmartPtr(new TFollowClass(a1));		
    	}	
    
    	template<typename A1, typename A2>
    	static CAutoSmartPtr CreateInstance(A1 a1, A2 a2)
    	{
    		return CAutoSmartPtr(new TFollowClass(a1, a2));	
    	}
    
    	template<typename A1, typename A2, typename A3>
    	static CAutoSmartPtr CreateInstance(A1 a1, A2 a2, A3 a3)
    	{
    		return CAutoSmartPtr(new TFollowClass(a1, a2, a3));	
    	}
    
    	template<typename A1, typename A2, typename A3, typename A4>
    	static CAutoSmartPtr CreateInstance(A1 a1, A2 a2, A3 a3, A4 a4 )
    	{
    		return CAutoSmartPtr(new TFollowClass(a1, a2, a3, a4));	
    	}
    
    	template<typename A1, typename A2, typename A3, typename A4, typename A5>
    	static CAutoSmartPtr CreateInstance(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
    	{
    		return CAutoSmartPtr(new TFollowClass(a1, a2, a3, a4, a5));	
    	}
    
    	CAutoSmartPtr & operator = (CAutoSmartPtr & src)
    	{
    		ptrrelease(); 
    		pshareptr = src.pshareptr; 
    		ptraddref();
    		return *this;
    	}
    	CAutoSmartPtr & operator = (void *pSrc)
    	{		
    		ptrrelease(); 
    		pshareptr = static_cast<TFollowClass *>(pSrc); 
    		if(pshareptr)
    			pshareptr->addref();
    		return *this;
    	}
    
    	CAutoSmartPtr(T * pSrc):pshareptr(static_cast<TFollowClass *>(pSrc))
    	{		
    		if(pshareptr)
    			pshareptr->addref();
    	}
    	
    
    	void CopyTo(void ** pp)
    	{
    		*pp = (void*)pshareptr;
    
    		if(pshareptr)
    			pshareptr->addref();
    	}
    	operator bool ()
    	{
    		return !!pshareptr->p;
    	}
    	void ** operator &()
    	{		
    		return (void**)&pshareptr;
    	}
    	T& operator * (){return *(static_cast<T*>(pshareptr));}
    	operator T*(){return static_cast<T*>(pshareptr);}
    	T* operator ->(){return static_cast<T*>(pshareptr);}
    	bool operator !(){return (pshareptr == NULL);}
    	bool operator <(T*pT){return static_cast<T*>(pshareptr) < pT;}
    	bool operator >(T*pT){return static_cast<T*>(pshareptr) > pT;}
    	bool operator != (T*pT) {return static_cast<T*>(pshareptr) != pT;}
    	bool operator == (T*pT) {return static_cast<T*>(pshareptr) == pT;}
    	
    };	

    测试
    CAutoSmartPtr<CTestClass> aspTest = CAutoSmartPtr<CTestClass>::CreateInstance();
    
     	CTestClass * pClass = aspTest;
    // 
     	pClass->Do(_T("class test"));
     	CAutoSmartPtr<CTestClass> aspTest2 = aspTest;
    // 
     	aspTest2->Do(_T("aspTest2->Do"));
    
    	struct foo
    	{
    		static void run(CTestClass * ptc, void ** pp)
    		{
     			CAutoSmartPtr<CTestClass> ssptc(ptc);
     			ssptc->Do(_T("run"));
     			CAutoSmartPtr<CTestClass2> ss2 = CAutoSmartPtr<CTestClass2>::CreateInstance(1000);
     			ss2.CopyTo(pp);
    		}
    	};
    
    	CAutoSmartPtr<CTestClass2> asp2;
    	foo::run(aspTest2, &asp2);
    // 
    // 	
    // 
    	CAutoSmartPtr<CTestClass2> aspTest3 = CAutoSmartPtr<CTestClass2>::CreateInstance(300);
    	aspTest3->Do(_T("aspTest3->Do"));
    
    	CAutoSmartPtr<CTestClass2> aspTest4 = CAutoSmartPtr<CTestClass2>::CreateInstance(40);

    输出
    CTestClass::CTestClass
    CTestClass::Do class test
    CTestClass::Do aspTest2->Do
    CTestClass::Do run
    CTestClass2::CTestClass2
    CTestClass2::CTestClass2
    CTestClass2::Do aspTest3->Do
    CTestClass2::CTestClass2
    CTestClass2::~CTestClass2 40
    CTestClass2::~CTestClass2 300
    CTestClass2::~CTestClass2 1000
    CTestClass::~CTestClass



用智能指针实行所有权 现在我们讨论下使用返回指针的函数的潜在错误。假设有一个函数返回一个指向某个MyClass类型的对象的指针。 MyClass* MyFactoryClass::Create(const Inputs& inputs); 这个函数的一个非常显而易见的问题是,它的调用者是否负责删除这个对象?或者说这个指针所指向的MyClass类的实例是MyFactoryClass所拥有的实例?这个问题显然应该在声明 阅读详情

相关推荐

C++智能指针线程安全深度解析:从引用计数到多线程实践

在C++多线程编程中,内存管理是核心挑战之一。智能指针通过自动化内存管理简化了资源生命周期控制,但其线程安全性常被误解。从原理上讲,智能指针的线程安全分为三个层次:引用计数操作的原子性、控制块本身的修改安全以及所管理对象的并发访问安全。其中,std::shared_ptr的引用计数操作是原子的,这为多线程环境下的对象生命周期管理提供了基础保障。然而,智能指针仅保证控制块安全,并不保证所管理对象内部状态的线程安全,这是许多开发者容易忽视的“坑”。在实际工程中,必须结合互斥锁、原子操作或线程安全设计模式来确保数

weixin_32576389的博客 290

c++:智能指针shared_ptr

先前的文章我们讲过了智能指针的概念等一系列问题,下面我们直接来看智能指针 1.带有引用计数的智能指针 (Shared_ptr)同时也是强智能指针 所谓的引用计数,就是有多少个智能指针对象管理这个堆内存。引用计数的作用是做所有对象共享的。 不可以写为普通的成员变量,要写成静态的成员变量 我们用一个引用计数管理器来实现Shared_ptr智能指针: 设计思路: 将引用计数管理器设计...

Kobe51920的博客 423

VTK学习-智能指针

VTK学习-智能 写在前面:智能指针在VTK编程中用的还是挺多的。而且智能指针并不是VTK独创的机制,而是借用C++中的概念,进行了自己的优化。那么就通过VTK智能指针的学习,强化指针这个概念,并且初步接触C++智能指针,让程序写的更加巧妙。

zy2317878的博客 1028

C++智能指针——share_ptr详解

前言 std::shared_ptr是在c++11中引入的一种智能指针,其特点是它所指向的资源具有共享性,即多个shared_ptr可以指向同一份资源。在c++中使用shared_ptr需要包含头文件。 共享指针是靠引用计数的方式来实现共享的功能,其中引用计数可以通过智能指针与引用计数详解文章了解。 std::shared_ptr常用函数介绍 std::shared_ptr的初始化有两种方法:...

yj_android_develop的博客 1万+

.NET适配HarmonyOS进展 1. 前言

目前国产化系统浪潮下,适配鸿蒙是中国软件大势所趋,.NET作为最适合开发客户端语言之一,适配鸿蒙系统(HarmonyOS Next)是目前.NET开发者最关心的事情。我目前业余时间正在移植Avalonia到HarmonyOS,去年在.NET Conf CN上分享过,目前又取得一点进展,所以本文把所有问题进行整合与大家进行分享。

2301_76476890的博客 1461

3dMax效率翻倍!用Octopus章鱼插件打造你的专属快捷菜单(附MaxScript入门指南)

本文详细介绍了如何利用Octopus插件和MaxScript脚本在3dMax中打造高效快捷菜单,显著提升三维建模与动画制作的工作效率。通过饼状菜单系统、自动化宏录制和脚本控制,用户可实现个性化工作流,节省大量操作时间。文章还提供了MaxScript入门指南,帮助开发者快速掌握这一强大工具。

weixin_30920853的博客 151

智能指针之share_ptr源码剖析以及线程安全测试

shared_ptr的实现 看了一下stl的源码,shared_ptr的实现是这样的: shared_ptr模板类有一个__shared_count类型的成员,_M_refcount来处理引用计数的问题。__shared_count也是一个模板类,它的内部有一个指针_M_pi。所有引用同一个对象的shared_ptr都共用一个_M_pi指针。 当一个shared_ptr拷贝复制时,...

weixin_30596343的博客 333

基于Python的高考志愿辅助填报系统

在实际应用中,系统需要处理更复杂的数据,包括更多的高校和专业信息、更详细的录取规则、以及用户的历史选择等。系统需要提供用户友好的界面,让考生输入自己的信息和偏好,然后通过后端的模型计算出推荐的志愿列表。此外,系统还应该提供一些个性化的服务,如根据考生的输入动态调整推荐策略、保存用户的填报历史和偏好等。特征可能包括考生的分数、所在省份、文理科类别、专业偏好、高校的地理位置、排名、专业的就业前景等。3. **推荐逻辑**:根据用户的分数和专业偏好,结合历史录取数据,使用简单的算法来推荐可能录取的高校和专业。

coder_wwwdy的博客 1976

c++智能指针详解

1.什么是智能指针 从比较简单的层面来看,智能指针是RAII(Resource Acquisition Is Initialization,资源获取即初始化)机制对普通指针进行的一层封装。这样使得智能指针的行为动作像一个指针,本质上却是一个对象,这样可以方便管理一个对象的生命周期。 在c++中,智能指针一共定义了4种: auto_ptr、unique_ptr、shared_ptr 和 weak_ptr。其中,auto_ptr 在 C++11已被摒弃,在C++17中已经移除不可用。 2.原始指针的问题 原始指

bitcarmanlee的博客 3万+

【XR硬件介绍】PICO Space Pro(Project Swan)深度解析:字节 2026 旗舰 MR 头显延期背后

内部代号 Project Swan 的 PICO 年度旗舰 MR 头显正式定名PICO Space Pro,原本计划 2026 年 9 月对外发布,官方官宣推迟至 2026 年第四季度上市。硬件层面已经完成 FCC 认证,硬件成熟度较高,延期核心目标是打磨 PICO OS 6 空间操作系统,补齐空间计算软件能力。本文从产品背景、硬件架构、软件生态、延期逻辑、行业竞争格局几个维度拆解这款国产高端 MR 设备,分析它对国内 XR 产业的意义与待解的问题。

houdou112358的博客 1168

Petalinux 2021.1 + Vivado 2021 实战:手把手教你为Zynq板卡移植Linux并搞定AXI DMA驱动

本文详细介绍了基于Petalinux 2021.1和Vivado 2021工具链,为Zynq开发板移植Linux系统并开发AXI DMA驱动的全流程。从环境配置、硬件设计到驱动适配与性能优化,提供了实战避坑技巧和版本特异性问题的解决方案,帮助开发者快速构建高速数据传输系统。

weixin_42641741的博客 386

c++11之智能指针

前言:面试的时候被问到智能指针了,答的很糟糕,这几天重新学习了智能指针。下面是我对c++智能指针的理解与总结,希望能帮到大家,同时提升自己。 一,什么是智能指针 在C++中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1.

qq_56673429的博客 2万+

Jenkins Job DSL:用代码管理CI/CD配置的实践指南

Jenkins 是持续集成(CI)领域的经典开源平台,其核心价值在于自动化构建与交付流程。然而传统 UI 配置方式导致配置不可版本化、难以复现、审计困难,严重制约团队规模化协作效率。Job DSL 作为一种声明式配置即代码(IaC)方案,通过 Groovy 脚本驱动 Jenkins 内部 API,实现 Job、View、Folder 等资源的程序化创建与维护,天然支持 Git 版本控制、权限审计与环境一致性保障。它不替代 Pipeline,而是与其协同构成‘流程定义’与‘基础设施定义’双轨体系,显著提升 C

weixin_33744141的博客 518

c++引用计数实现简单智能指针

原始指针 SmartPoint.h class BaseClass { int x_; public: BaseClass(int x) : x_(x) {}; ~BaseClass() {}; }; 单一类型智能指针实现 SmartPoint.h #ifndef SMARTPOINT_BASECLASS_H #define SMARTPOIT_BASECLAS...

Nick_Zhang_优快云的博客 597

《FPGA DDR3权威实战:从基础到高速故障录波系统》专栏导览:从不知所措到心中有数

本文是一份DDR3实战指南,作者从自身学习经历出发,分享了一套循序渐进的DDR3应用路线图。专栏包含12篇文章,从基础配置(MIG IP核、AXI总线)、仿真测试到实际项目应用(功能测试、性能测试),最后深入原生MIG接口实战,通过一个高速故障录播系统案例完整展示DDR3开发流程。文章特别强调实践性,旨在帮助读者系统掌握DDR3开发技能,避免作者当年踩过的坑。每篇都配有优快云链接,适合FPGA开发者按顺序学习参考。

FPGA_小田老师的博客 331

【原创教程】西门子1500与施耐德伺服的通讯以及调试

该函数块主要描述伺服的手动,左边的引脚Forward是指伺服手动正转,Backward是指伺服手动反转,Fast是指手动的某个方向为快速运行,TipPos手册上描述为固定值,WaitTIme是指伺服手动的相应时间,VeloSlow指伺服手动正常慢速运动的速度,VeloFast指伺服手动快速运动的速度,Acceleration是指伺服手动的加速度,Decelertion是指伺服手动的减速度。该函数块用于伺服停止,左边的引脚Execute为伺服停止执行,Deceleration含义为减速,Axis为轴。

Qinmingyue13的博客 1374

C++ 智能指针

shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保在离开指针所在作用域时,自动正确地销毁动态分配的对象,防止内存泄漏。它的一种通用实现技术是使用引用计数,每使用它一次,内部的引用计数加1,每析构1次,内部引用计数减1,减为0时,删除所指向的堆内存。当你有一个指向某个类型的指针时,你可以使用解引用操作符来获取或修改该指针所指向的变量的值。这会导致所管理对象的引用计数减少,如果引用计数变为零,对象将被销毁。

weixin_51883798的博客 796

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C++11 智能指针:从原理到实现

本文深入探讨了C++11智能指针的实现原理与使用方式。智能指针通过RAII技术自动管理内存资源,有效解决了传统C++手动内存管理的诸多问题。文章重点分析了三种智能指针:unique_ptr实现独占所有权,禁止拷贝但支持移动语义;shared_ptr通过引用计数实现共享所有权;weak_ptr作为弱引用可解决循环引用问题。每种智能指针都配有详细代码示例,展示了创建、操作和资源管理的关键用法。最后还通过简化实现揭示了unique_ptr和shared_ptr的内部工作机制,包括引用计数和自定义删除器的实现细节。

2301_80541270的博客 1445

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

share_ptr: 智能指针

1、多态性 1.1多态性是面向对象程序设计的关键技术之。若程序设计语言不支持多态性,不能称为面向对象的语言。利用多态性技术,可以调用同一个函数名的函数,实现完全不同的功能。 在C+ +中有中两种多态性: 编译时的多态 通过函数的重载和运算符的重载来实现的。 int Max(int a, int b) { return a > b ? a : b; } char Max(char a, char b) { return a > b ? a : b; } double Max(double

qq_46615150的博客 955

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

用原始指针初始化智能指针的一些问题

class A{}; int main() { A* a = new A; cout << a << endl; shared_ptr<A> p(a); //delete a; cout << p.use_count() << endl; cout << p << endl; cout &...

znHD的博客 2551

C++ - 智能指针

注意:std::unique_ptr 不支持复制(不可复制),只能移动(通过 std::move)。

5266的博客 508

【c++11 篇】智能指针-shared_ptr

智能指针产生原因:c++中不像java 自带垃圾回收机制,必须释放掉分配的内存,否则就会造成内存泄露。因此c++11引入了智能指针。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动的销毁分配的对象,防止内存泄露。原理:智能指针的核心实现技术是引用计数,每使用它一次内部引用计数加1,每析构一次内部引用计数减1,减为0时,删除原始指针指向的堆区内存使用智能指针需要引用头文件<memory>。sharedptr共享的智能指针u。

2401_85061293的博客 863

带引用计数的智能指针

带引用计数的智能指针shared_ptr和weak_ptr带引用计数:多个智能指针可管理同一个资源。

qq_42120843的博客 350

智能指针和引用计数 -- c++学习笔记

如何来让指针知道还有其他指针的存在呢?这个时候我们该引入引用计数的概念了。引用计数是这样一个技巧,它允许有多个相同值的对象共享这个值的实现。引用计数的使用常有两个目的:简化跟踪堆中(也即C++中new出来的)的对象的过程。一旦一个对象通过调用new被分配出来,记录谁拥有这个对象是很重要的,因为其所有者要负责对它进行delete。但是对象所有者可以有多个,且所有权能够被传递,这就使得内存跟踪变得困难。引用计数可以跟踪对象所有权,并能够自动销毁对象。可以说引用计数是个简单的垃圾回收体系。

m0_67700979的博客 867

C++智能指针与原始指针的性能博弈:何时该如何抉择?

以std::shared_ptr为例,它使用引用计数来管理对象的生命周期,每次复制或销毁std::shared_ptr对象时,都需要对引用计数进行原子操作,这会带来额外的CPU指令周期。然而,智能指针也带来了一定的性能开销。在多线程环境中,智能指针也能有效避免资源竞争和内存泄漏问题,虽然引用计数的原子操作会带来一定开销,但相比于手动管理内存可能出现的错误,这种开销是值得的。此外,在与C语言库进行交互时,原始指针也是必不可少的,因为C语言中没有智能指针的概念,使用原始指针可以避免类型转换带来的额外开销。

2501_91651722的博客 561

C++智能指针的本质是什么?

C++智能指针本质上是对原始指针的封装,借助于资源所有权和引用计数等机制,实现了自动内存管理,确保了资源的正确释放。通过智能指针,我们可以避免手动内存管理中常见的错误,如内存泄漏和悬挂指针,从而提高了代码的健壮性和可维护性。随着C++11的引入,智能指针作为一个新的语言特性被提出,旨在简化内存管理,自动管理内存的生命周期,确保内存资源的安全性。除了标准库提供的智能指针,开发者还可以根据需求实现自定义的智能指针。C++标准库提供了几种主要的智能指针,每种智能指针有不同的内存管理策略,适用于不同的场景。

CppPlayer 1112
上一篇: ini文件另一种读取办法
下一篇: 金融行业密钥体系介绍 摘自http://www.360doc.com/content/12/0210/22/7430724_185676018.shtml#
魔芋
博客等级 码龄26年 37粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值