c++11-智能指针

c++智能指针
为了更安全地管理动态内存,c++11引入了智能指针,提供了包括shared_ptr,unique_ptr,weak_ptr三种不同类型的智能指针。

目录结构:
一、三种指针介绍
1.shared_ptr
2.unique_ptr

二、shared指针的基本使用
1.创建shared_ptr对象的两种方法
2.智能指针的使用
3.引用计数
4.复位引用计数函数reset
5.获取C指针函数get

三、shared_ptr指针使用的注意细节
1.不能用栈空间的C指针构造共享指针
2.不能用一个C指针构造一个以上的共享指针

四、智能指针实现多态

一、三种指针介绍
1.shared_ptr
shared_ptr是使用最为广泛的智能指针,推荐shared_ptr为首选智能指针。

2.unique_ptr
std::unique_ptr是C++11标准中用来取代std::auto_ptr的指针容器(在C++11中,auto_ptr被废弃)。它不能与其它unique_ptr类型的指针对象共享所指对象的内存,意味着只能有一个unique_ptr指向特定的对象。这种”所有权”仅能够通过标准库的move函数来转移。unique_ptr是一个删除了拷贝构造函数、保留了移动构造函数的指针封装类型,因此它不能够拷贝和赋值。

unique_ptr<cls> p1(new cls); 	//unique_ptr初始化
unique_ptr<cls> p2 = p1 		//错误,unique_ptr不支持赋值
unique_ptr<cls> p2(p1); 		//错误,unique_ptr不支持拷贝
p1.reset();	//释放p1指向的内存, p1置空;unique_ptr成员函数reset;
auto ptr = p1.release();//返回普通指针,p1置空,需要执行"delete ptr;"释放内存;

二、shared_ptr指针的基本使用
1.创建shared_ptr对象的两种方法:
a. make_shared
它是最为高效的和安全的创建共享指针的方法,执行后会在堆中分配内存资源并初始化。
b. new
shared_ptr提供了构造函数,以new的方式进行shared_ptr对象的构造。

#include <iostream>
#include <thread>

using namespace std;

class Test
{
public:
	Test():age_m(0)
	{
		cout << "调用Test构造函数" << endl;
	}

	~Test()
	{
		cout << "调用Test析构函数" << endl;
	}

	int getAge()
	{
		return age_m;
	}
	void setAge(int age)
	{
		age_m = age;
	}
private:
	int age_m;
};

int main()
{
	shared_ptr<Test> ptr(new Test());
	shared_ptr<Test> makePtr = make_shared<Test>();
	cout << ptr->getAge() << endl;
	return 0;
}

//打印结果
root@epc:/home/share/eclipse_workspace/exercise/src#  ./exercise
调用Test构造函数
调用Test构造函数
0
调用Test析构函数
调用Test析构函数
root@epc:/home/share/eclipse_workspace/exercise/src#

2.shared_ptr指针的使用
shared_ptr指针的使用就是指向原始对象的指针,可以用->访问原始对象的成员,可以用*进行解引用。但它也是一个类对象,它有get成员函数(可以获取原始对象的地址),use_count成语昂函数(返回引用计数)等。

3.引用计数
每个shared_ptr都有一个关联的计数值,通常称为引用计数。无论何时我们拷贝复制一个shared_ptr,计数器都会递增,而且会传递到被拷贝对象。
例如,当用一个shared_ptr初始化另一个shared_ptr,或将它当作参数传递给一个函数以及作为函数的返回值时,它所关联的计数器都会递增。
当我们给shared_ptr赋予一个新值或是shared_ptr被销毁.例如一个局部的shared_ptr离开其作用域时,计数器就会递减。
一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理的shared_ptr。

#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

class Test
{
public:
	Test()
	{
		cout << "调用Test构造函数" << endl;
	}

	~Test()
	{
		cout << "调用Test析构函数" << endl;
	}
};

int main()
{
	shared_ptr<Test> ptr(new Test());
	shared_ptr<Test> makePtr = make_shared<Test>();
	cout << "初始化后的引用计数ptr=" << ptr.use_count() << endl;
	cout << "初始化后的引用计数makePtr=" << makePtr.use_count() << endl;

	ptr = makePtr;	//赋值后,ptr原对象引用计数减1即为0,执行析构函数;而makePtr的引用计数加1,makePtr的引用计数传递;
	cout << "赋值后的引用计数ptr=" << ptr.use_count() << endl;
	cout << "赋值后的引用计数makePtr=" << makePtr.use_count() << endl;

	return 0;
}
//打印结果
root@epc:/home/share/eclipse_workspace/exercise/src#  ./exercise
调用Test构造函数
调用Test构造函数
初始化后的引用计数ptr=1
初始化后的引用计数makePtr=1
调用Test析构函数
赋值后的引用计数ptr=2
赋值后的引用计数makePtr=2
调用Test析构函数
root@epc:/home/share/eclipse_workspace/exercise/src#

三、shared_ptr指针使用的注意细节
1.不能用栈空间的C指针构造共享指针
共享指针在析构的时候会执行delete函数,如果是非new构造,系统会报错;

2.不能用一个C指针构造一个以上的共享指针
用一个C指针构造多个共享指针时,共享指针的引用计数都是单独计算,因此会执行多次delete函数。

//错误的用法
T *a = new T();
shared_ptr<T> ptr1(a);
shared_ptr<T> ptr2(a);

四、智能指针实现多态
题外话:
很多时候c++多态和重载被人混淆,在这里有必要解释一番;
重载:指在一个类中,允许函数名相同但参数类型或者个数不同的成员函数定义;
多态:指派生类和基类中都有相同的成员函数(指函数名和参数都相同);当基类的这个函数为虚函数时,此时派生类的成员函数拥有了覆盖的能力;否则,派生类的成员函数拥有隐藏的能力;

#include <iostream>
#include <memory>
#include <string>

using namespace std;

class Base
{
public:
	Base()
	{
		cout << "基类构造函数" << endl;
	}
	
	virtual ~Base()
	{
		cout << "基类析构函数" << endl;
	}

	virtual void display()
	{
		cout << "Base::display()" << endl;
	}
};

class Derived : public Base
{
public:
	Derived(): Base()
	{
		cout << "派生类构造函数" << endl;
	}
	
	virtual ~Derived()
	{
		cout << "派生类析构函数" << endl;
	}

	virtual void display()
	{
		cout << "Derived::display()" << endl;
	}
};


int main()
{
	shared_ptr<Base> ptr(new Derived);		//shared_ptr
	//unique_ptr<Base> ptr(new Derived);	//unique_ptr,执行unique_ptr时,请将上一行注释掉
	ptr->display();
	return 0;
}
//执行shared_ptr的打印结果
root@epc:/home/share/test#  ./test
基类构造函数
派生类构造函数
Derived::display()
派生类析构函数
基类析构函数
root@epc:/home/share/test#

//执行unique_ptr的打印结果
root@epc:/home/share/test#  ./test
基类构造函数
派生类构造函数
Derived::display()
派生类析构函数
基类析构函数
root@epc:/home/share/test# 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值