动态内存和智能指针及其实现方法

本文深入探讨了三种智能指针(shared_pointer, unique_pointer 和 DebugDelete 类)的实现细节,并通过示例代码展示了它们的工作原理及如何在 C++ 中使用这些自定义智能指针。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >






DebugDelete.h


#ifndef DEBUGDELETE_H
#define DEBUGDELETE_H

#include <iostream>

/**
* @brief The DebugDelete class is a deleter functor using delete
*/
class DebugDelete
{
public:
	DebugDelete(std::ostream& s = std::cerr) : os(s) { }
	template<typename T>
	void operator() (T* p) const
	{
		os << "deleting ptr" << std::endl;
		delete p;
	}

private:
	std::ostream& os;
};
#endif // DEBUGDELETE_H


shared_pointer.h

#ifndef SHARED_POINTER_H
#define SHARED_POINTER_H

#include "DebugDelete.h"
#include <functional>

//! forward declarations needed for friendship

template<typename> class shared_pointer;

template<typename T> void swap(shared_pointer<T>& lhs, shared_pointer<T>& rhs);


/**
*  @brief shared_ptr like template class
*  @note   don't mix this one with std::shared_ptr.
*          DebugDelete is the default deleter which can be replaced at run time
*/
template <typename T>
class shared_pointer
{
	friend void swap<T>(shared_pointer<T>& lhs, shared_pointer<T>& rhs);
	//!             ^^^ -- don't forget this.

public:

	//! default constructor
	shared_pointer() = default;

	//! constructor taking raw pointer.
	//! set the refCount as 1
	explicit shared_pointer(T* up, std::function<void(T*)> d = DebugDelete()) :
		ptr(up), refCount(new std::size_t(1)), deleter(d) { }

	//! copy constructor.
	//! increment useCount for each Copy
	shared_pointer(const shared_pointer& sp) :
		ptr(sp.ptr), refCount(sp.refCount), deleter(sp.deleter)
	{
		++*refCount;
	}

	//! move constructor
	shared_pointer(shared_pointer&& sp) /*noexcept*/;

	//! copy assignment
	shared_pointer& operator =(const shared_pointer& rhs);

	//! move assignment
	shared_pointer& operator =(shared_pointer&& rhs) /*noexcept*/;




	//! conversion operator
	operator bool() const { return ptr ? true : false; }

	//! dereference
	T& operator* () const { return *ptr; }

	//! arrow
	T* operator->() const { return &this->operator *(); }

	//! return useCount
	std::size_t use_count() const { return *refCount; }

	//! get the underlying pointer
	T* get() const /*noexcept*/{ return ptr; }

	//! check if the unique user
	bool unique() const /*noexcept*/{ return *refCount == 1; }

	//! swap
	void swap(shared_pointer& rhs) { ::swap(*this, rhs); }

	//! if unique user, free the object pointed to
	void reset() /*noexcept*/{ decrement_n_destroy(); }

	//! make prt point where p pointing and create a new coount for it
	void reset(T* p)
	{
		if (ptr != p)
		{
			decrement_n_destroy();
			ptr = p;
			refCount = new std::size_t(1);
		}
	}

	//! reset to point where p is pointing and change deleter to d.
	void reset(T *p, const std::function<void(T*)>& d)
	{
		reset(p);
		deleter = d;
	}




	//! destructor
	~shared_pointer()
	{
		decrement_n_destroy();
	}
private:

	//! data structure
	T* ptr = nullptr;
	std::size_t* refCount = new std::size_t(0);

	//! any functor lambda or function pointer that matched this
	//! signature can replace the default one at run time.
	std::function<void(T*)> deleter{ DebugDelete() };
	//! signature ^^^^^^^^         ^~~~~~~~~~~~~~^
	//!                         here: = doesn't work, another way is initializing it in constructor.

	//! utilities
	void decrement_n_destroy();

};



/**
*  @brief swap and big 5
*/
template <typename T>
inline void
swap(shared_pointer<T>& lhs, shared_pointer<T>& rhs)
{
	using std::swap;
	swap(lhs.ptr, rhs.ptr);
	swap(lhs.refCount, rhs.refCount);
	swap(lhs.deleter, rhs.deleter);
}


//! move constructor
template<typename T>
inline
shared_pointer<T>::shared_pointer(shared_pointer&& sp)/* noexcept*/ :
ptr(sp.ptr), refCount(sp.refCount), deleter(std::move(sp.deleter))
{
	sp.ptr = nullptr;
	sp.refCount = nullptr;
}

//! copy assignment
template<typename T>
inline shared_pointer<T>&
shared_pointer<T>::operator =(const shared_pointer& rhs)
{
	//! increment rhs.refCount first to ensure safty when self-assignment
	++*rhs.refCount;

	//! for lhs:
	decrement_n_destroy();

	//! copy datastructure from rhs to this.
	ptr = rhs.ptr;
	refCount = rhs.refCount;
	deleter = rhs.deleter;

	return *this;
}


//! move assignment
template<typename T>
inline shared_pointer<T>&
shared_pointer<T>::operator =(shared_pointer&& rhs) /*noexcept*/
{
	//! for lhs
	decrement_n_destroy();

	//! swap two sides
	::swap(*this, rhs);

	std::cout << "shared_pointer::move=\n";

	return *this;
}

/**
*@brief operators:
**/

template <typename T>
inline std::ostream&
operator <<(std::ostream& os, shared_pointer<T> p)
{
	os << p.get();
	return os;
}


//! utilities for decrement and delete using deleter.
template <typename T>
inline void
shared_pointer<T>::decrement_n_destroy()
{
	if (ptr)
	{
		if (--*refCount == 0)
		{
			delete refCount;
			deleter(ptr);
		}
		refCount = nullptr;
		ptr = nullptr;
	}
}

#endif // SHARED_POINTER_H

unique_pointer.h

#ifndef UNIQUE_POINTER_H
#define UNIQUE_POINTER_H

#include "DebugDelete.h"

//! forward declarations for friendship

template<typename, typename> class unique_pointer;
template<typename T, typename D> void
swap(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs);

/**
*  @brief  std::unique_ptr like class template.
*/
template <typename T, typename D = DebugDelete>
class unique_pointer
{
	friend void swap<T, D>(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs);

public:
	//! preventing copy and assignment
	unique_pointer(const unique_pointer&) = delete;
	unique_pointer& operator = (const unique_pointer&) = delete;

	//! default constructor and one taking T*
	unique_pointer() = default;
	explicit unique_pointer(T* up) : ptr(up) { }

	//! move constructor
	unique_pointer(unique_pointer&& up) /*noexcept*/
		: ptr(up.ptr)   {
		up.ptr = nullptr;
	}

	//! move assignment
	unique_pointer& operator =(unique_pointer&& rhs) /*noexcept*/;

	//! std::nullptr_t assignment
	unique_pointer& operator =(std::nullptr_t n) /*noexcept*/;



	//! operator overloaded :  *  ->  bool
	T& operator  *() const   { return *ptr; }
	T* operator ->() const   { return &this->operator *(); }
	operator bool() const   { return ptr ? true : false; }

	//! return the underlying pointer
	T* get() const /*noexcept*/{ return ptr; }

	//! swap member using swap friend
	void swap(unique_pointer<T, D> &rhs)  { ::swap(*this, rhs); }

	//! free and make it point to nullptr or to p's pointee.
	void reset()     /*noexcept*/{ deleter(ptr); ptr = nullptr; }
	void reset(T* p) /*noexcept*/{ deleter(ptr); ptr = p; }

	//! return ptr and make ptr point to nullptr.
	T* release();


	~unique_pointer()
	{
		deleter(ptr);
	}
private:
	T* ptr = nullptr;
	D  deleter = D();
};


//! swap
template<typename T, typename D>
inline void
swap(unique_pointer<T, D>& lhs, unique_pointer<T, D>& rhs)
{
	using std::swap;
	swap(lhs.ptr, rhs.ptr);
	swap(lhs.deleter, rhs.deleter);
}

//! move assignment
template<typename T, typename D>
inline unique_pointer<T, D>&
unique_pointer<T, D>::operator =(unique_pointer&& rhs) /*noexcept*/
{
	//! prevent self-assignment
	if (this->ptr != rhs.ptr)
	{
		deleter(ptr);
		ptr = nullptr;
		::swap(*this, rhs);
	}
	return *this;
}


//! std::nullptr_t assignment
template<typename T, typename D>
inline unique_pointer<T, D>&
unique_pointer<T, D>::operator =(std::nullptr_t n) /*noexcept*/
{
	if (n == nullptr)
	{
		deleter(ptr);   ptr = nullptr;
	}
	return *this;
}

//! relinquish contrul by returnning ptr and making ptr point to nullptr.
template<typename T, typename D>
inline T*
unique_pointer<T, D>::release()
{
	T* ret = ptr;
	ptr = nullptr;
	return ret;
}
#endif // UNIQUE_POINTER_H

test.c

#include <iostream>
#include <vector>
#include <memory>
#include <functional>
#include "DebugDelete.h"
#include "shared_pointer.h"
#include "unique_pointer.h"


void main()
{
	std::vector<unique_pointer<int>> v;

	for (int u = 0; u != 10; ++u)<pre name="code" class="sql">deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
deleting ptr
0
1
2
3
4
5
6
7
8
9
请按任意键继续. . .

v.push_back(unique_pointer<int>(new int(u)));for (auto& sp : v)std::cout << *sp << "\n";system("pause");}


Running result:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值