什么是智能指针,何时使用?

什么是智能指针,何时使用

更新

这个答案相当古老,因此描述了什么是“好的”,这是Boost库提供的智能指针。自C++11以来,标准库提供了足够的智能指针类型,因此您应该支持使用std::unique\u ptrstd::shared\u ptrstd::weak\u ptr

还有std::auto_ptr。它与作用域指针非常相似,只是它还具有“特殊”的危险复制能力,这也意外地转移了所有权。
它在C++11中被弃用,在C++17中被删除,因此您不应该使用它

std::auto\u ptr<MyObject>p1(新的MyObject());
标准::自动测试<MyObject>p2=p1;//复制和转让所有权。
//p1设置为空!
p2->DoSomething();//作品
p1->DoSomething();//噢。希望引发一些空指针异常。

旧答案

智能指针是一个包一个“原始”(或“裸”)C++指针,用来管理指向的对象的生命周期的类。没有单一的智能指针类型,但它们都试图以实用的方式抽象原始指针

智能指针应该优先于原始指针。如果你觉得你需要使用指针(首先考虑一下,如果你真的DO),你通常会想使用一个智能指针,因为这可以减轻很多原始指针的问题,主要是忘记删除对象和泄漏内存。

对于原始指针,当对象不再有用时,程序员必须显式销毁对象

//需要创建对象来实现某些目标
MyObject*ptr=新的MyObject();
ptr->DoSomething();//以某种方式使用对象
删除ptr;//销毁该对象。完了。
//等等,如果DoSomething()引发异常怎么办。。。?

通过比较,智能指针定义了一个关于何时销毁对象的策略。您仍然需要创建对象,但不必再担心会破坏它

SomeSmartPtr<MyObject>ptr(newmyobject());
ptr->DoSomething();//以某种方式使用对象。
//对象的破坏会发生,具体取决于
//在智能指针类使用的策略上。
//即使使用DoSomething()也会发生破坏
//引发了一个例外

使用中最简单的策略涉及智能指针包装器对象的范围,例如通过boost::scoped_ptrstd::unique_ptr实现

void f()
{
{
std::unique_ptr<MyObject>ptr(新MyObject());
ptr->dosomethingusseve();
}//ptr超出范围--
//MyObject将自动销毁。
//ptr->Oops();//编译错误:“ptr”未定义
//因为它已经不在范围之内了。
}

请注意,无法复制std::unique_ptr实例。这样可以防止多次(错误地)删除指针。但是,您可以将对它的引用传递给您调用的其他函数

std::unique_ptrs在您希望将对象的生存期绑定到特定的代码块时非常有用,或者如果您将其作为成员数据嵌入到另一个对象中,则另一个对象的生存期。对象存在,直到包含的代码块退出,或者直到包含的对象本身被销毁

更复杂的智能指针策略涉及指针的引用计数。这允许复制指针。当对象的最后一个“引用”被销毁时,该对象将被删除。此策略由boost::shared_ptrstd::shared_ptr实现

void f()
{
typedef std::shared_ptr<MyObject>MyObjectPtr;//很好的短别名
MyObjectPtr p1;//为空
{
MyObjectPtr p2(新MyObject());
//现在创建的对象有一个“引用”
p1=p2;//复制指针。
//现在有两个对对象的引用。
}//p2已销毁,只留下一个对该对象的引用。
}//p1被销毁,留下的引用计数为零。
//对象将被删除。

当对象的生存期要复杂得多,并且没有直接绑定到特定代码段或其他对象时,引用计数指针非常有用

引用计数指针有一个缺点-可能会创建悬挂引用:

//在堆上创建智能指针
MyObjectPtr*pp=新的MyObjectPtr(新的MyObject())
//嗯,我们忘了摧毁智能指针,
//正因为如此,物体永远不会被摧毁!

另一种可能性是创建循环引用:

结构所有者{
std::共享\u ptr<所有者>其他;
};
标准::共享\u ptr<业主>p1(新所有者());
标准::共享\u ptr<业主>p2(新所有者());
p1->其他=p2;//p1引用p2
p2->其他=p1;//p2引用p1
//哎呀,p1和p2的参考计数永远不会变为零!
//这些东西永远不会被摧毁!

为了解决这个问题,Boost和C++11都定义了一个弱\u ptr来定义对共享\u ptr的弱(未计算)引用

发表评论