浅谈CPP智能指针

智能指针其实并不是指针,而是一个特殊对象。
在智能指针对象生命期即将结束时,它会调用析构函数释放有它管理的堆内存。
访问智能指针管理对象的方法,使用操作符“->”(重载)。
访问智能指针本来的方法,使用操作符“.”。

我们常见的智能指针有以下几种:

C98
std::auto_ptr
第一代智能指针,有些操作比如“=”坑比较多,不推荐使用。

C11
std::unique_ptr
独占对象,并保证指针所指对象生命周期与其一致。

std::shared_ptr
可共享指针对象,可以赋值给shared_ptr或weak_ptr。
通过引用计数的方式控制生命周期,当指针所指对象的所有的shared_ptr生命周期结束时(引用计数为0时)会被销毁。

std::weak_ptr
可以指向shared_ptr,但并不影响引用计数。
不影像所指对象的生命周期,在引用所指对象时,先用需要lock()才能使用。

Boost
不共享对象,类似于std::unique_ptr
boost::scoped_ptr
boost::scoped_array

共享对象,类似于std::shared_ptr
boost::shared_ptr
boost::shared_array

共享对象,但不改变对象引用计数,类似于std::weak_ptr
boost::weak_ptr

侵入式引用计数,要求使用对象自己实现计数功能
boost::intrusive_ptr

下面给一个例子,说明一下std下的四种智能指针。
1、SmartPointerTest.cpp

#include <memory>
#include <iostream>
#include "MyTest.h"

using namespace std;

void test_auto_ptr()
{
	std::auto_ptr<MyTest> auto_ptr_01(new MyTest("tom", 20));

	if (auto_ptr_01.get())
	{
		auto_ptr_01->sayHello();
		auto_ptr_01.get()->_name = "jerry";
		auto_ptr_01->sayHello();
		(*auto_ptr_01)._age += 1;
		auto_ptr_01->sayHello();
	}
	
	//auto_ptr_02会抢占auto_ptr_01的对象
	//此后auto_ptr_01不指向MyTest对象
	std::auto_ptr<MyTest> auto_ptr_02 = auto_ptr_01;
	if (auto_ptr_01.get())
	{
		cout << "auto_ptr_01 is released" << endl;
	}
	auto_ptr_02->sayHello();

	//只是释放所有权,并不释放内存
	//MyTest* test = auto_ptr_02.release();

	//释放内存
	auto_ptr_02.reset();
	if (!auto_ptr_01.get())
	{
		cout <<"auto_ptr_02 is released"<< endl;
	}
	
}

void test_unique_ptr()
{
	//独占对象
	//保证指针所指对象生命周期与其一致
	unique_ptr<MyTest> unique_ptr_01(new MyTest("tom", 20));
	unique_ptr_01->sayHello();

	//不允许直接做右值
	//unique_ptr<int> unique_ptr_02 = unique_ptr_01;

	//需要通过move来处理
	unique_ptr<MyTest> unique_ptr_03 = move(unique_ptr_01);
	if (!unique_ptr_01)cout << "unique_ptr_01 is empty" << endl;
	unique_ptr_03->sayHello();

	//释放指针
	unique_ptr_03.reset();
	if (!unique_ptr_03)cout << "unique_ptr_03 is empty" << endl;
}

void test_shared_ptr()
{
	shared_ptr<MyTest> shared_ptr_01(make_shared<MyTest>("tom", 20));
	shared_ptr<MyTest> shared_ptr_02 = shared_ptr_01;
	shared_ptr_01->sayHello();
	shared_ptr_02->sayHello();

	shared_ptr_01.reset();
	if (!shared_ptr_01)cout << "shared_ptr_01 is empty" << endl;
	shared_ptr_02->sayHello();

	shared_ptr_02.reset();
	if (!shared_ptr_02)cout << "shared_ptr_02 is empty" << endl;
}

void test_weak_ptr()
{
	shared_ptr<MyTest> shared_ptr_01(make_shared<MyTest>("tom", 20));
	weak_ptr<MyTest> weak_ptr_01 = shared_ptr_01;
	shared_ptr_01->sayHello();
	weak_ptr_01.lock()->sayHello();

	weak_ptr_01.reset();
	if (!weak_ptr_01.lock())cout << "weak_ptr_01 is empty" << endl;
	shared_ptr_01->sayHello();
	
	weak_ptr<MyTest> weak_ptr_02 = shared_ptr_01;
	weak_ptr<MyTest> weak_ptr_03 = weak_ptr_02;
	if(weak_ptr_01.lock())weak_ptr_02.lock()->sayHello();
	shared_ptr_01.reset();
	if (!weak_ptr_01.lock())cout << "weak_ptr_02 is empty" << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	test_auto_ptr();
	test_unique_ptr();
	test_shared_ptr();
	test_weak_ptr();

	return 0;
}

2、MyTest.h

#pragma once

#include <iostream>
#include <string>

using namespace std;

class MyTest
{
public:
	MyTest(string name, int age);
	~MyTest();
	void sayHello();

public:
	string _name;
	int _age;
};

3、MyTest.cpp

#include "stdafx.h"
#include "MyTest.h"

MyTest::MyTest(string name, int age)
{
	_name = name;
	_age = age;
}

MyTest::~MyTest()
{
}

void MyTest::sayHello()
{
	cout << "Hello " << _name<< "! You are "<< _age <<" years old." << endl;
}

PS:
聪明的你有没有发下,CPP的智能指针,与JVM内存中的四种引用方式,强引用、软引用、弱引用,虚引用,有很多相似的地方呢?

Leave a Reply

Your email address will not be published. Required fields are marked *

*