C++的智能指针
Class: C++ClassByMyself
参考: The Cherno相关课程
内容不全,笔记自投。
智能指针实现了new与delete的很大一部分功能,说白了实现自动化了。
智能指针的实质是实现了原始指针的封装。
- 智能指针本质上是原始指针的包装。当你创建一个智能指针,它会调用new并为你分配内存,然后基于你使用的智能指针,这些内存会在某一时刻自动释放。
- 优先使用unique_ptr,其次考虑shared_ptr。
尽量使用unique_ptr因为它有一个较低的开销,但如果你需要在对象之间共享,不能使用unique_ptr的时候,就使用shared_ptr
unique_ptr
- unique_ptr构造函数实际上是explicit的,没有构造函数的隐式转换,需要显式调用构造函数。
- 最好使用
std::unique_ptr<Entity> entity = std::make_unique<Entity>();因为如果构造函数碰巧抛出异常,不会得到一个没有引用的悬空指针从而造成内存泄露,它会稍微安全一些。 std::make_unique<>()是在C++14引入的,C++11不支持。
#include <iostream>
#include <memory>
class Entity
{
private:
public:
Entity()
{
std::cout << "Create!" << std::endl;
}
~Entity()
{
std::cout << "Destroy!" << std::endl;
}
void Print(){}
};
int main()
{
{
//使用unique_ptr的一种方式
std::unique_ptr<Entity> entity = new Entity(); // error! unique_ptr不能隐式转换
std::unique_ptr<Entity> entity(new Entity());//ok,可以但不建议
std::unique_ptr<Entity> entity = std::make_unique<Entity>(); //推荐使用std::make_unique。因为如果构造函数碰巧抛出异常,它会稍微安全一些。std::make_unique<>()是在C++14引入的,C++11不支持。
entity->Print(); //像一般原始指针使用
}
std::cin.get();
}
share_ptr
- 跟踪你的指针有多少个引用,一旦引用计数达到零,他就被删除了。
引用计数基本上是一种方法,可以跟踪你的指针有多少个引用,一旦引用计数达到零,他就被删除了。
例如:我创建了一个共享指针shared_ptr,我又创建了另一个shared_ptr来复制它,我的引用计数是2,第一个和第二个,共2个。当第一个死的时候,我的引用计数器现在减少1,然后当最后一个shared_ptr死了,我的引用计数回到零,内存就被释放。
- shared_ptr需要分配另一块内存,叫做控制块,用来存储引用计数,如果您首先创建一个new Entity,然后将其传递给shared_ptr构造函数,它必须分配,做2次内存分配。先做一次new Entity的分配,然后是shared_ptr的控制内存块的分配。然而如果你用make_shared你能把它们组合起来,这样更有效率。
怎么说呢,这两次内存分配,第一次是实例化调用构造函数时做出的内存分配
第二次是,share_ptr本身特性造成的,它需要开辟一个存储计数的内存块
所以make_shared的组合出现了(C17),还是优先用吧!!!
std::shared_ptr<Entity> sharedEntity = sharedEntity(new Entity());//不推荐!
std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();//ok
- unique_ptr和shared_ptr的一个显著区别在于,前者唯一不可复制,后者的主要用处就在于复制!
int main()
{
{
std::shared_ptr<Entity> e0;//这里就算一个引用了
{
// std::shared_ptr<Entity> sharedEntity = sharedEntity(new Entity());//不推荐!
std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();//ok
e0 = sharedEntity; //可以复制
} //此时sharedEntity已经“死了”,但没有调用析构,因为e0仍然是活的,并且持有对该Entity的引用,此时计数由2-》1
} //析构被调用,因为所有的引用都消失了,计数由2-》0,内存被释放
std::cin.get();
}
弱指针weak_ptr (这玩意的使用主要看需求)
1.可以和共享指针shared_ptr一起使用。
2.weak_ptr可以被复制,但是同时不会增加额外的控制块来控制计数,仅仅声明这个指针还活着。
当你将一个shared_ptr赋值给另外一个shared_ptr,引用计数++,而若是
把一个shared_ptr赋值给一个weak_ptr时,它不会增加引用计数
{
std**::**weak_ptr**<**Entity**>** e0;
{
std**::**shared_ptr**<**Entity**>** sharedEntity **=** std**::**make_shared**<**Entity**>**();
e0 **=** sharedEntity;
} *//此时,此析构被调用,内存被释放*
}
&spm=1001.2101.3001.5002&articleId=147288650&d=1&t=3&u=fe1227e2eda0478ba141d1cfb952a590)
872

被折叠的 条评论
为什么被折叠?



