0

我有几个关于智能指针的问题,之前我没有给他们任何信任。

  1. 在智能指针的世界中,拥有一个对象、指向一个对象和管理一个对象意味着什么?之前我认为拥有该对象的人也指向它并管理该对象。现在,我知道智能指针可以拥有一个对象,但指向另一个对象(别名构造函数)。在这里,我找到了一个很好的解释,解释了拥有一个对象的含义-> http://www.umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf,但我仍然无法区分这三个术语。
  2. 如果指针拥有一个对象,但指向另一个对象,他管理的是哪个对象?他拥有它的那个,还是他指向的那个,或两者兼而有之?拥有一个对象但不指向它有什么意义?
  3. 两个智能指针何时相等?两个指针可以同时拥有同一个对象并不同吗?我对他们的价值平等不感兴趣,但对所有权感兴趣。
  4. 为什么所有权顺序很重要(除了将指针用作容器中的键)?我想这仅与 shared_ptr 相关。

一切都是从试图理解 owner_before 开始的,现在我比开始探索这个话题之前更加困惑了.. :(

4

3 回答 3

1

我认为您所有的困惑都来自“别名构造函数”:

template <typename U>
shared_ptr(const shared_ptr<U>& x, element_type* p)

这东西有什么用?好吧,它很少使用,但它的作用是“共享”某个对象的所有权,x但是当您取消引用它时,您会得到它p。就这样。它永远不会删除它p或对它做任何其他事情。

如果你有这样的东西可能会很有用:

struct Foo {
    Bar bar;
};

struct Baz {
    Baz(shared_ptr<Bar> bar) : m_bar(bar) {}
    shared_ptr<Bar> m_bar;
};

int main()
{
    auto foo = make_shared<Foo>();
    Baz baz(shared_ptr<Bar>(foo, &foo.bar));
}

现在baz可以在foo不知道它在做什么的情况下管理 a 的生命周期——它只关心它管理 a 的生命周期Bar,但由于我们bar是 的一部分foo,我们不能在不破坏的foo情况下进行破坏bar,因此我们使用别名构造函数。

但实际上,我们不这样做,因为这种用例非常罕见。

于 2016-12-14T13:15:13.217 回答
0

所有权

您的困惑是因为所有权不是编译器可以验证的;作为程序员,你需要推断它。

如果存在保证存在(最好没有内存泄漏) ,我们可以说任何对象p 拥有。 简单的情况是直接所有权,其中解除分配也会解除分配,例如,如果是 的成员,或者使用in的析构函数显式解除分配。 智能指针让人们明白这一点。如果存储在一个成员中,我们就知道拥有。您无需四处搜索(可能丢失或重复)删除语句。qpq
pqqpqdeletep
qstd::unique_ptrppq

所有权也是传递的,如果p拥有qq拥有r,那么p必须拥有r

别名

如果p直接拥有q,并且我们要创建一个shared_ptr拥有的q,那么它也必须拥有p。否则,如果p被销毁,那么q也会被销毁,尽管我们的共享指针存在。

这就是 std::shared_ptr 的别名构造函数所做的(在约翰的回答中得到证明)。

q通过延长 的生命周期来延长p的生命周期,所以我们有一个指向q它实际拥有的指针pp我们向实际上拥有的编译器断言q,因此共享的 ptr 传递地拥有q

如果p不拥有q,那么您的程序将编译,但它已损坏,就像您手动调用delete两次一样。

比较

对于 stl 智能指针,比较传递给原始指针。因此,如果智能指针取消引用同一对象,则它们是相等的,并且比较是关于内存位置的。没有任何已定义的行为来指定内存位置,因此除了存储在 amapset.

于 2016-12-14T16:42:09.577 回答
0

旧的“原始”指针:

someType* pR = new someType(param1, param2); //pR is a pointer
MyOwner.TakeOwnershipOf(pR); // Now MyOwner is the owner, **the one who ONLY should call 'delete pR;'**

智能指针:

std::shared_ptr<someType> sp = std::make_shared<someType>(param1, param2);

“sp”现在是所有者(代码中没有“pR”,但在内部它是)。而且您不需要调用“删除 pR”。它是一个在内部存储指向 pR 的指针并在不再需要时将其删除的对象。

sp 是一个对象。“sp->any”与“pR->any”完全相同。这会让你对 sp 也是一个指针感到困惑。不,碰巧“->”被重载了。

更重载:

sp.get()是一样的pR*sp是相同的*pR

sp1 == sp2相同pR1 == pR2和相同sp1.get()==sp2.get()

shared_ptr的好处是,例如,当您需要在多个容器中存储相同的指针时。如果某个容器被删除,存储的指针(sp,谁拥有 pR)也应该被删除。这将使存储在其他容器中的指针无效。shared_ptr 不是检查其他容器是否存在这个指针,而是负责它。也就是说,您可以安全地删除sp,因为pR只会被存储的最后一个容器删除sp

于 2016-12-14T16:34:30.810 回答