由于添加了一个指向矢量的指针,我的程序失败了。经过多次阅读和删除后,我已将其更改为添加到集合中的共享指针(使用插入),这在开始时很好但现在也失败了。我试过two solutions;既没有奏效。一个失败了,另一个,make共享类,没有编译。
再多读一遍,我发现这个forum指出,我不应该用两个不同的共享指针指向某个东西,而是创建它的副本。那么共享指针的最大区别是什么?
答案 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 ++代码(它编译)。但是,p1
和p2
现在都认为它们拥有指针。由于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_ptr
和shared_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
作为其名称。
例如 - 类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是正确的。这是确保在销毁集时清理对象的正确方法。