c++智能指针实现

已知面试官常问c++大型程序内存泄露怎么办,同学们通常会回答使用智能指针,智能指针可以避免使用new来初始化对象带来的delete问题,智能指针的实现思路是raii思想。

unique_ptr即独占式智能指针,一个对象无法复制到其他unique_ptr,当然也无法进行值传递给函数。

unique_ptr堆内存空间是独有的,它的引用计数为1,一旦放弃指向的资源,资源会自动回收释放。

unique_ptr构造方法

#include<memery>
using namespace std;
unique_ptr<int>p();
unique_ptr<int>p(nullptr);
unique_ptr<int>p(new int);
unique_ptr<int>p(move(q));//移动构造函数调用

值得一提的是,unique_ptr不支持拷贝构造函数。

unique_ptr成员函数

release  释放当前指针的所有权,堆空间不会被释放

swap,get等。

重载了*,=,->,[],

unique_ptr用法如上图所示,需要注意的是release和reset用法,release释放原来智能指针后用int*类型变量接替,而reset则反过来使用unique_ptr来接替int*类型,unique_ptr最好初始化一个nullptr。 

值得注意的是,使用release后,智能指针将被析构不存在,而reset方法保留原有原始指针的使用值。

unique_ptr传入函数作为参数时无法通过值传递,但可以通过引用传递,另外,可以通过get方法获得裸指针传入,也可以使用move语义将智能指针交给函数管理

 值得注意的是,通过右值引用传入函数后,原指针依旧存在并可用。推荐简单的值传递。

另一个值得注意的点是函数的传值,传引用,传右值引用并不构成重载

 unique_ptr具体实现

只能实现简易版的,可能和原版有差异,例如析构问题

C++手把手带你实现一个智能指针 - 知乎 (zhihu.com)

 以下是代码实现:

#pragma once
#ifndef _UNIQ_PTR_
#define _UNIQ_PTR_
#include<cstdio>
#include<iostream>

using namespace std;

template<typename T>
class uniq_ptr
{
public:
	uniq_ptr() {}
	uniq_ptr(T* rawptr) :m_rawptr(rawptr) { delete rawptr; cout << "利用原始指针创建成功" << endl;  }
	uniq_ptr(uniq_ptr<T>&u_ptr) = delete;
	uniq_ptr<T>& operator=(unique_ptr<T>&u_ptr) = delete;
	uniq_ptr(uniq_ptr<T>&&u_ptr) noexcept
	{
		T* rawptr = u_ptr.get();
		m_rawptr = rawptr;
		rawptr = nullptr;
		cout << "移动构造函数创建成功" << endl;
	}

	unique_ptr<T>& operator=(unique_ptr<T>&&u_ptr) noexcept
	{
		m_rawptr = u_ptr.m_rawptr;
		u_ptr.m_rawptr = nullptr;
		cout << "可以复制但是原来智能指针被析构" << endl;
		return *this;
	}

	~uniq_ptr() { m_rawptr=nullptr; }

	T& operator*()
	{
		return *m_rawptr;
	}
	T* operator->()
	{
		return m_rawptr;
	}
	operator bool()
	{
		return m_rawptr == nullptr;
	}

	T* get()
	{
		return m_rawptr;
	}
	T* release()
	{
		T* rawptr = m_rawptr;
		m_rawptr = nullptr;
		return rawptr;
	}
	uniq_ptr<T>&reset(T* rawptr)
	{
		m_rawptr = rawptr;
		return *this;
	}



private:
	T* m_rawptr;
};
#endif 

创建数组对象

二. shared_ptr

共享指针即一个对象可以由多个指针托管,当所有托管指针都不再托管该对象时,对象才会被析构,共享指针可以通过reset来重置所指对象。get方法获得共享指针的原始指针。

C++11 shared_ptr智能指针(超级详细) (biancheng.net)

与unique_ptr不同的是,shared_ptr有use_count函数用来判断有多少共享指针指向该对象,unique函数判断是否只有一个共享指针指向该对象。但共享指针没有release函数。

以下是代码实现

#pragma once
#include<bits/stdc++.h>
using namespace std;

template <typename T>
class smart_ptr
{
public:
	// 构造和析构
	explicit smart_ptr(T* ptr ) :ptr_(ptr)
	{
		shared_count = nullptr;
		if (ptr)
		{
			shared_count = new long(1);
		}
	}
	~smart_ptr()
	{
		if (ptr_ && --(*shared_count) == 0)  // 析构空指针不能减少引用计数
		{
			delete ptr_;
			delete shared_count;
		}
	}
	// 拷贝构造和拷贝赋值运算符
	smart_ptr(const smart_ptr& other)
	{
		ptr_ = other.ptr_;
		shared_count = other.shared_count;    // 浅拷贝
		if (ptr_) // 非空才能增加引用计数
		{
			(*shared_count)++;
		}
	}

	smart_ptr& operator=(const smart_ptr& other) // 普通的拷贝赋值
	{
	    if (&other == this) return *this;
	    if (ptr_ && --(*shared_count) == 0)  
	    {
	        delete ptr_;
	        delete shared_count;
	    }
	    ptr_ = other.ptr_;
	    shared_count = other.shared_count;
	    if(ptr_) (*shared_count)++;
	    return *this;
	}


	// 移动构造和移动赋值运算符, 只需要转移资源,不需要自增
	smart_ptr(smart_ptr&& other)
	{
		ptr_ = other.ptr_;
		shared_count = other.shared_count;
		other.ptr_ = nullptr;
		other.shared_count = nullptr;

	}


	// 成员方法
	T* get()
	{
		return ptr_;
	}
	T* release()
	{
		if (ptr_ && --(*shared_count) == 0)
		{
			delete ptr_;
			ptr_ = nullptr;
			delete shared_count;
			shared_count = nullptr;
		}
		return ptr_;
	}
	void reset(T* ptr )
	{
		release();
		ptr_ = ptr;
		shared_count = ptr_ ? new long(1) : nullptr;
	}
	long use_count()
	{
		if (ptr_ && shared_count) return *shared_count;
		return 0;
	}
	void swap(smart_ptr& p1, smart_ptr& p2)
	{
		using std::swap;
		swap(p1, ptr_, p2.ptr_);
		swap(p1.shared_count, p2.shared_count);
	}


	// 运算符 * -> 重载和bool转换函数
	T& operator*() const
	{
		return *ptr_;
	}
	T* operator->() const
	{
		return ptr_;
	}
	explicit operator bool() const
	{
		return ptr_;
	}
private:
	T* ptr_;
	long* shared_count;
};

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值