共享指针的处理是什么?

时间:2011-09-16 04:12:46

标签: c++ shared-ptr

由于添加了一个指向矢量的指针,我的程序失败了。经过多次阅读和删除后,我已将其更改为添加到集合中的共享指针(使用插入),这在开始时很好但现在也失败了。我试过two solutions;既没有奏效。一个失败了,另一个,make共享类,没有编译。

再多读一遍,我发现这个forum指出,我不应该用两个不同的共享指针指向某个东西,而是创建它的副本。那么共享指针的最大区别是什么?

3 个答案:

答案 0 :(得分:3)

所有关于所有权。如果实体(函数或对象)是该实体的工作以确保指针被删除,则该实体(函数或对象)被称为“拥有”指针。任何时候使用new,某人某处必须取得所返回指针的所有权。如果不是这种情况,则会发生内存泄漏。

各种智能指针的目的是为某种形式的所有权建模。智能指针的析构函数可以触发删除指针。

std::auto_ptr(只要你不复制它)模型单一所有权。也就是说,任何具有auto_ptr实例的实体都是导致该指针被破坏的实体。由于hackery,复制auto_ptr实际上将所有权从复制的对象转移到要复制的对象(注意:永远不要这样做)。

所以,如果你有这个:

std::auto_ptr<int> p1 = new int(4);

这保证会被销毁(只要持有它的实体被正确清理)。当p1从堆栈中掉落时,指针将被销毁。如果p1是类的成员,那么当该类实例被销毁时,指针将被销毁。指针的生命周期是作用域。 Boost实际上有一个名为boost::scoped_ptr的不可复制的等价物。

使用任何类型的智能指针时,您必须遵守几条规则。这是最重要的。

规则#1:如果您从指针构造智能指针实例,您所说的是“没有对象当前拥有此指针的所有权。我我现在给你所有权,智能指针。“这就是从裸指针构造智能指针对象的意思。

此代码违反了规则#1:

std::auto_ptr<int> p1 = new int(4);
std::auto_ptr<int> p2 = p1.get();

auto_ptr::get()函数返回指针,因此这是合法的C ++代码(它编译)。但是,p1p2现在都认为它们拥有指针。由于auto_ptr仅模拟 - 所有权,因此不允许这样做。当p2被销毁时,它将删除指针。然后,当p1被销毁时,它将尝试删除相同的指针。

糟糕。

现在我们对规则#1非常清楚,让我们看一下shared_ptr。此智能指针模拟共享所有权。多个实体可以同时声明指针的所有权。仅当所有使用它时,才会删除指针。因此,如果3个对象都包含shared_ptr到同一个对象,则在删除包含shared_ptr的所有三个对象之前,不会删除该对象。

了解shared_ptr是智能指针非常重要。因此,它受规则#1的约束。

这可能没有意义。毕竟,它应该允许共享所有权。这必须意味着这是允许的,对吗?

shared_ptr<int> p1 = new int(4);
shared_ptr<int> p2 = p1.get();

不。这仍然是错误的。 auto_ptrshared_ptr之间的区别在于您可以使用shared_ptr执行此操作:

shared_ptr<int> p1 = new int(4);
shared_ptr<int> p2 = p1;

这是来自p2的{​​{1}}的副本构造。从裸指针创建p1和从已存在的shared_ptr创建一个shared_ptr之间存在根本区别。后者实际上是两者之间的所有权。前者只会造成不良。

因此,如果您有一个裸指针并将其放在shared_ptr中,则只能对该指针进行一次如果要共享所有权,则必须复制它。

有一个半后门:enable_shared_from_this。如果从这种类型派生一个类,那么你的类将有一个shared_from_this私有成员,该类的成员函数可以使用它来转移所有权。所以:

struct Type : public enable_shared_from_this
{
  DoSomething()
  {
    shared_ptr<Type> p2 = shared_from_this();
    FunctionThatTakesOwnership(p2);
  }
};

shared_ptr<Type> p1 = new Type;
p1->DoSomething();

除此之外,您必须通过明确复制对象来转移所有权。

答案 1 :(得分:2)

如果从不同的地方引用shared_ptr指向的对象,则应使用

shared_ptr作为其名称。

例如 - 类A1和A2应该使用类型S的相同对象。因此两者都应该保存指向S的指针。但是谁只拥有它(谁应该删除它)。我们说A1。因此,它的析构函数中的A1将删除S.但是如果在A2之前销毁A1会发生什么 - A2会将悬空指针(指向已删除对象的指针)转换为S.使用shared_ptr而不是指向S(S *)的原始指针可以解决此问题。

答案 2 :(得分:0)

指向的对象的共享指针取得所有权

这样做的语义是,当复制shared_ptr时,每个人共享一个句柄来分享他们对所有权的共享知识。当最后一个副本被销毁时,它会销毁该对象。这使您无需在正确的时间手动管理对delete的调用,并且(希望)使内存泄漏更少。

为了使这项工作正常,通常的方法是在创建shared_ptr时给它一个new堆对象,然后避免直接使用原始指针。

在STL集中使用shared_ptr是正确的。这是确保在销毁集时清理对象的正确方法。