TIP💡

关于智能指针中的基础知识可以看一下 对象生存周期

智能指针 unique_ptr

unique_ptr 是作用域指针,超过作用域时会进行销毁,在 对象生存周期中提及的作用域指针其实就是 unique_ptr。
Unique_ptr 指针从字面意思理解就是指该指针是独一无二的,而事实上也确实如此。unique_ptr指针不能复制,因为复制之后两者指向的是同一个内存空间,当其中一个指针关闭时,会销毁指向的内存空间,导致两者指向已回收的内存。

#include<memory>
class Entity
{
public:
    Entity()
    {
        std::cout << "创建对象" << std::endl;
    }
    ~Entity()
    {
        std::cout << "销毁对象" << std::endl;
    }
    void print() {}
};
 
int main()
{
    {
        std::unique_ptr<Entity> entity(new Entity());
        //使用make_unique创建unique_ptr会更加安全
        //可避免构造函数异常时变成没有引用的悬空指针
        std::unique_ptr<Entity> entity = std::make_unique<Entity>();
		//下列做法是错误的
		std::unique_ptr<Entity> e0 = entity;    
        entity->print();
    }
}

智能指针 shared_ptr

Shared_ptr 相比 unique_ptr,可以从字面意思上看出 shared_ptr 可以共享(复制)。Shared_ptr 通过引用计数来决定是否销毁,如果没有对象引用该指针,即引用计数为 0 时,指针将会自动销毁。

#include<memory>
class Entity
{
public:
    Entity()
    {
        std::cout << "创建对象" << std::endl;
    }
    ~Entity()
    {
        std::cout << "销毁对象" << std::endl;
    }
    void print() {}
};
 
int main()
{
	//例子1
    {
        std::shared_ptr<Entity> entity(new Entity());
		//shared_ptr需要分配额外内存给控制块,记录引用计数
		//使用make_shared可以更高效地分配内存
        std::shared_ptr<Entity> entity = std::make_shared<Entity>();
		//shared_ptr可以进行复制
		std::shared_ptr<Entity> e0 = entity;
    }
 
	//例子2
	{
		std::shared_ptr<Entity> e0;
		{
			//此时引用计数变为1
			std::shared_ptr<Entity> shared_entity = std::make_shared<Entity>();
			//引用计数变为2
			e0 = shared_entity;
		}//离开shared_entity的作用域,引用计数变为1
	}//离开e0的作用域,引用计数变为0,entity对象销毁
 
	{
		//weak_ptr不会增加引用计数
		std::weak_ptr<Entity> e0;
	    {
	  		//此时引用计数变为1
	  		std::shared_ptr<Entity> shared_entity = std::make_shared<Entity>();
	  		//引用计数仍然为1
	  		e0 = shared_entity;
	  	}
	  	//离开shared_entity的作用域,引用计数变为0,销毁entity对象
	  	//e0指向一个无效的Entity对象
	}
}

Weak_ptr 指针与 shared_ptr 唯一的区别在于不增加引用计数,对于对象的有效性和所属权并不关心的时候,可以使用 weak_ptr 指针,weak_ptr 可以指向存活的对象,但是不能保活

Comment

智能指针可以有效地自动化管理内存,如果在代码中不需要显式地调用 delete 管理内存,那么使用智能指针是一个不错的选择。其中 shared_ptr 相比 unique_ptr ,有额外的引用计数,因此有着更高的系统开销,所以在使用智能指针时应优先考虑 unique_ptr,如果存在对象间共享的需求,再考虑 shared_ptr。