生命周期
在这里再次强调了栈和堆上声明变量的区别。
{
Entity e;
Entity* e1 = new Entity();
}
使用局部作用域创建的变量不要返回局部变量。解决这一方法有两种:
1.在堆上创建变量,如上所示。
2.使用指针接收返回。
智能指针示例:
class ScopedPtr {
private:
Entity* m_Ptr;
public:
ScopedPtr(Entity* ptr) : m_Ptr(ptr) {}
~ScopedPtr()
{
delete m_Ptr;
}
};
智能指针使用场景:比如在一个类中要统计某对象从生成到析构的使用时间,就可以使用智能指针自动计算。
智能指针、联合指针这是作用域指针,还有很多例子,最简单的例子就是作用域指针了,本质上就是一个类,一个指针的包装类。
智能指针
在使用智能指针的时候会带来一些便捷操作,包括不限于不用手动释放内存、可以不用new关键词等,自动化内存管理,防止因为忘记调用delete意外泄露内存,不想显性调用new和销毁delete的时候应该使用智能指针。智能指针包括几种:
1.unique_ptr
unique_ptr是最简单的智能指针,开销很低,一般情况下主要推荐用这个,不能copy,以下为其几种声明方法:
std::unique_ptr<Entity> entity(new Entity());
std::unique_ptr<Entity> entity = std::make_unique<Entity>();
//这是最好的做法,因为涉及异常安全问题考虑,这对unique_ptr来说很重要
以下为其几个错误使用案例:
std::unique_ptr<Entity> entity = new Entity();
错误,因为unique_ptr实现的构造函数是explicit,这里不能隐形转换
std::unique_ptr<Entity> e0 = entity;
不能这么做,copy构造和方法被删除了,一旦有一个这种指针死掉,其他的也会都死掉
2.shared_ptr
shared_ptr会额外分配一块叫做控制块的内存,用来存储引用计数,当所有的共享指针都死亡了,内存才会被释放。
std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
std::shared_ptr<Entity> sharedEntity1(new Entity());
3.weak_ptr
std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
sharedEntity2 = sharedEntity;
std::weak_ptr<Entity> = sharedEntity;
这里不会增加引用计数,当把shared_ptr赋值给另一个时,它会增加引用计数,但是把shared_ptr赋值给一个weak_ptr时,不会增加计数,因此当你不想获得Entity所有权,则会非常有用,就像你可能在对一个Entity列表进行排序,并不关心它们是否有效,只需要存储一个引用就可以,可以通过weak_ptr去判断底层对象是否存活,因为不会增加引用计数,所以不能保证底层对象一直存活。