c++智能指针

智能指针

智能指针是RAII(Resource Acquisition Is Initialization,资源获取即初始化)机制对普通指针进行的一层封装。这样使得智能指针的行为动作像一个指针,本质上却是一个对象,这样可以方便管理一个对象的生命周期。在c++中,智能指针一共定义了4种:
auto_ptr、unique_ptr、shared_ptr 和 weak_ptr。其中,auto_ptr 在 C++11已被摒弃,在C++17中已经移除不可用。
智能指针能对堆区声明的内存自动释放,保证了内存管理的安全,不会出现野指针,使用智能指针需要添加头文件

#include <memory>

1.unique_ptr

不允许进行拷贝,只允许一个unique_ptr对象持有指针,因为多个unique_ptr对象持有同一个指针时,会对该指针指向的内存多次释放
unique_ptr的初始化方式

std::unique_ptr<int> valuePtr(new int(47));

也可以使用默认构造函数,再使用reset方法重新设置指针,注:如果使用reset方法之前unique_ptr对象本身就有指针,那么会先将原有指针释放掉,再设置新的指针

std::unique_ptr<int> valuePtr; 
valuePtr.reset(new int(47));

unique_ptr支持移动语义,可以将一个unique_ptr对象所持有的指针复制给另一个对象

#include <iostream>
#include <memory>
#include <utility>
 
int main()
{
    std::unique_ptr<int> valuePtr(new int(15));
    std::unique_ptr<int> valuePtrNow(std::move(valuePtr));
 
    std::cout << "valuePtrNow = " << *valuePtrNow << '\n';
    std::cout << "Has valuePtr an associated object? "
              << std::boolalpha
              << static_cast<bool>(valuePtr) << '\n';
}

代码输出为

valuePtrNow = 15
Has valuePtr an associated object? false

2.shared_ptr

shared_ptr是一种引用计数指针,当引用计数为零时,会自动对指针所指向的内存进行释放,可以进行函数间的引用传递。这一特性可以用于基于类和对象编程中,存储一个类成员变量的指针并将其引用传递到类之外使用

#include <memory>
 
class Foo
{
	public void doSomething();
};
 
class Bar
{
private:
	std::shared_ptr<Foo> pFoo;
public:
	Bar()
	{
		pFoo = std::shared_ptr<Foo>(new Foo());
	}
 
	std::shared_ptr<Foo> getFoo()
	{
		return pFoo;
	}
};

在上面的代码中,创建一个Bar对象会创建一个Foo对象的指针,存储在Bar对象的私有成员变量中,可以通过Bar的getFoo方法获取该指针,getFoo方法中会调用std::shared_ptr 的拷贝构造函数创建一个Foo对象的引用并将计数加一,下面调用这个类

void SomeAction()
{
	Bar* pBar = new Bar(); //with the Bar object, a new Foo is created and stored
	//reference counter = 1
 
	std::shared_ptr<Foo> pFoo = pBar->getFoo(); //a copy of the shared pointer is created
	//reference counter = 2
 
	pFoo->doSomething(); 
 
	delete pBar; //with pBar the private pFoo is destroyed
	//reference counter = 1
 
	return; //with the return the local pFoo is destroyed automatically 
	//reference counter = 0
	//internally the std::shared_ptr destroys the reference to the Foo object
}

我们无需手动删除pFoo,简化了内存管理

void SomeOtherAction(std::shared_ptr<Bar> pBar)
{
	std::shared_ptr<Foo> pFoo = pBar->getFoo(); //a copy of the shared pointer is created
	//reference counter = 2
 
	pFoo->doSomething(); 
 
	return; //local pFoo is destroyed
	//reference counter = 1
}

函数返回后,pBar被删除,但是还是会保留一个引用

循环引用问题

shared_ptr最大的坑就是循环引用。引用网络上的一个例子:
循环引用: link

3.weak_ptr

C++11标准虽然将weak_ptr定位为智能指针的一种,但该类型指针通常不单独使用(实际没有用处),只能和shared_ptr类型指针搭配使用。甚至于,我们可以将weak_ptr类型指针视为shared_ptr指针的一种辅助工具,借助weak_ptr类型指针,我们可以获取shared_ptr指针的一些状态信息,比如有多少指向相同的shared_ptr指针,shared_ptr指针指向的堆内存是否已经被释放等等。
  需要注意的是,当weak_ptr类型指针的指向和某一shared_ptr指针相同时,weak_ptr指针并不会使所指堆内存的引用计数加1;同样,当weak_ptr指针被释放时,之前所指堆内存的引用计数也不会因此而减1。也就是说,weak_ptr类型指针并不会影响所指堆内存空间的引用计数。
  除此之外,weak_ptr模板类中没有重载*和->运算符,这也就意味着,weak_ptr类型指针只能访问所指的堆内存,而无法修改它。

成员方法功能
operator=()重载=赋值运算符,weak_ptr指针可以直接被weak_ptr或者shared_ptr类型指针赋值
swap(x)其中x表示一个同类型的weak_ptr类型指针,该函数可以互换2个共同类型weak_ptr指针的内容
reset()将当前weak_ptr指针置为空指针
use_count()查看指向和当前weak_ptr指针相同的shared_ptr指针的数量
expired()判断当前weak_ptr指针是否过期(指针为空,或者指向的堆内存已经被释放)
lock()如果当前weak_ptr已经过期,则该函数会返回一个空的shared_ptr指针;反之,该函数返回一个和当前weak_ptr指针指向相同的shared_ptr指针。

使用smart_ ptr允许我们传递和返回对对象的引用,而不会出现内存泄漏或访问已删除引用的无效尝试。因此,它们是现代内存管理的基石。

参考:
https://en.cppreference.com/book/intro/smart_pointers
https://blog.csdn.net/bitcarmanlee/article/details/124847634

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值