c++智能指针

c++11新特性引入完善了智能指针,来动态管理内存,可自动释放内存,避免了内存泄漏和悬挂指针的问题,方便资源管理。

头文件 :

#include <memory>
类名描述
unique_ptr独占所指向的对象,同一时刻只能有一个 unique_ptr 指向给定对象(通过禁止拷贝语义, 只有移动语义来实现)
shared_ptr可以共享对象,计数
weak_ptr配合 shared_ptr 来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少.
auto_ptr已废弃

unique_ptr

        unique_ptr,独占智能指针,提供对动态分配的单一对象所有权的管理。因为独占所指向对象,所以同一时刻只有一个实例。其指向给定的内存资源,不能被拷贝,不能值传递,只能移动语义和右值引用允许其在所有权转移时高效地进行转移。当其被销毁时可自动释放所管理的资源。

unique_ptr的使用

#include <iostream>
#include <memory>
#include <string>
using namespace std;
 
class Test
{
public:
	Test() {
		cout << "Test()" << endl;
	}
	~Test() {
		cout << "~Test()" << endl;
	}
	void Output()const {
		cout << "Output()" << endl;
	}
};

unique_ptr<string> fun(const string& str)
{
	return make_unique<string>(str);
}

int main() {

	unique_ptr<int> u1 = make_unique<int>(10);
	unique_ptr<int> u2(new int(20));
	cout<<"*u1="<< *u1 << endl;
	cout<<"*u2="<< *u2 << endl;
    
    unique_ptr<int> u3 = move(u1);	    // 移动语义,u1的内存释放,u1的内存交给u3管理
    cout<<"u1.get()="<<u1.get()<<endl;  //输出为nullptr
    cout<<"u3.get()="<<u3.get()<<endl;
    cout<<"*u3="<<*u3<<endl;
    
    unique_ptr<string> u4 = fun("hello world!");
	cout << *u4 << endl;
    
    unique_ptr<Test> u5 = make_unique<Test>();
    unique_ptr<Test> u6(new Test);
	u5->Output();
    u6->Output();
    
    unique_ptr<int[]> u7(new int[5]);
    for (int i = 0; i < 5; ++i) {
        u7[i] = i ;
    }
    for (int i = 0; i < 5; ++i) {
        cout<<u7[i]<<" ";
    }
    cout<<endl;
    
	return 0;
}

unique_ptr的实现

template <class T>
class UniquePtr
{
public:
	UniquePtr(T* ptr) {
		this->ptr = ptr;
	}
	~UniquePtr() {
		if (ptr != nullptr)delete ptr;
	}
	T& operator*() {
		return *ptr;
	}
	T* get() {
		return ptr;
	}
	T* operator->() {
		return ptr;
	}
private:
	UniquePtr(const UniquePtr&) = delete;
	UniquePtr& operator=(const UniquePtr&) = delete;
private:
	T* ptr;
};

shared_ptr

        允许多个智能指针共享同一块内存资源。内部使用引用计数来跟踪对象被共享地次数,当计数为0时,资源被释放。提供更灵活地内存共享,但可能存在循环引用地问题。

shared_ptr的使用

#include <iostream>
#include <memory>
#include <string>
using namespace std;

class B;
class A
{
public:
	A() { cout << "A::A() called " << endl; }
	~A() { cout << "~A::~A() called " << endl; }
	shared_ptr<B>p;
	//weak_ptr<B>p;  //加入weak_ptr可避免引用成环
};
class B
{
public:
	B() { cout << "B::B() called " << endl; }
	~B() { cout << "~B::~B() called " << endl; }
	//shared_ptr<A>p;
	//weak_ptr<A>p;
};


int main() {

    shared_ptr<int>s1 = make_shared<int>(10); 
	//shared_ptr<int>s1(new int(10));	//new表达式作为构造函数参数,其效率低。多使用 make_shared
	shared_ptr<int>s2(s1); //拷贝构造
	shared_ptr<int>s3=s2;  //重载
	cout << "*s1="<< *s1 <<",s1.use_count()=" << s1.use_count() << ",s1.get()" << s1.get() << endl;
	cout << "*s2="<< *s2 <<",s2.use_count()=" << s2.use_count() << ",s2.get()" << s2.get() << endl; 
	cout << "*s3="<< *s3 <<",s3.use_count()=" << s3.use_count() << ",s3.get()" << s3.get() << endl;

    //关于引用成环的问题
	shared_ptr<A> pA(new A);
	shared_ptr<B> pB(new B);
	//下面两句导致了A与B的循环引用,结果就是A和B对象都不会析构
 	pA->p = pB;
 	pB->p = pA;
	cout << "pA use_count:" << pA.use_count() << endl;
	cout << "pB use_count:" << pB.use_count() << endl;

	return 0;
}

shared_ptr的实现

template <class T>
class SharedPtr {
public:
	SharedPtr() : ptr(nullptr), cnt(nullptr) {
	}

	SharedPtr(T *p) : ptr(p), cnt(nullptr) {
		if (ptr) {
			cnt = new int(1);
		}
	}

	SharedPtr(SharedPtr &other) : SharedPtr() {
		ref(other);
	}

	~SharedPtr() {
		unRef();
	}

	int use_count() const {
		if (cnt) return *cnt;
		return 0;
	}

	T &operator*() {
		return *ptr;
	}

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

	T *operator->() {
		return ptr;
	}

	const T *operator->() const {
		return ptr;
	}

	SharedPtr &operator=(SharedPtr &other) {
		unRef();
		ref(other);
		return *this;
	}
private:
	void ref(SharedPtr &other) {
		if (other.ptr) {
			ptr = other.ptr;
			cnt = other.cnt;
			++(*cnt);
		}
	}

	void unRef() {
		if (cnt) {
			--(*cnt);
			if (*cnt == 0) {
				delete ptr;
				delete cnt;
			}
		}
	}
private:
	T	*ptr;
	int *cnt;
};

weak_ptr

        用于解决共享指针可能导致的循环引用问题。

        可从共享指针创建,但不会增加引用计数,不会影响资源的释放。

        通过weak_ptr::lock()可以获取一个共享指针来访问资源。

weak_ptr实例化

#include <iostream>
#include <memory>
#include <string>
using namespace std;

class B;
class A
{
public:
	A() { cout << "A::A() called " << endl; }
	~A() { cout << "~A::~A() called " << endl; }
	shared_ptr<B>p;
	//weak_ptr<B>p;  //加入weak_ptr可避免引用成环
};
class B
{
public:
	B() { cout << "B::B() called " << endl; }
	~B() { cout << "~B::~B() called " << endl; }
	//shared_ptr<A>p;
	//weak_ptr<A>p;
};

weak_ptr<A>get() {
	shared_ptr<A>p1(new A);
	return p1;
}

int main() {

	weak_ptr<A> p2 = get();
	shared_ptr<A> P3 = p2.lock();
	cout << P3 << endl;
	if (P3) {
		cout << "对象可用" << endl;
	}
	else
	{
		cout << "对象不可用" << endl;
	}

	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值