scoped_ptr所有权

12

可能是重复问题:
什么是智能指针,何时使用?

我正在阅读一篇文章,其中有一个小例子演示了如何使用boost::scoped_ptr<T>

#include <cstdlib>
#include <iostream>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

static int count = 0;

class printer
{
    int m_id;

public:
    printer(void) :
        m_id(count++)
    {
    }

    ~printer(void)
    {
        std::cout << "Printer " << m_id
                  << " destroyed" << std::endl;
    }
};

int
main(void)
{
    boost::scoped_ptr<printer> p1(new printer);
    boost::scoped_ptr<printer> p2(new printer);
    std::cout << "Exiting test program" << std::endl;

    return EXIT_SUCCESS;
}
文章中唯一让我不明白的是这句话:

使用scoped_ptr表明不打算或不允许所有权转移。


也许对于初学者来说,这篇文章并不适合。但是上面这句话到底是什么意思呢?

是的,那篇文章不对。这个问题的答案是一本完整的C++书,但是SO不允许我发布那么长的答案。 - Lightness Races in Orbit
整本C++书?好的!虽然我真的很怀疑..你能否尝试给一个简要概述呢?我会尽力理解的。 - SandBag_1996
你尝试过把答案分成两个,每个答案都不那么长的方式来发布吗? - thang
@thang:是啊 :( 我只做到了1/16大小的帖子,然后就放弃了。 - Lightness Races in Orbit
@LightnessRacesinOrbit 所以理论上,您可以发布16篇每篇1/16长度的帖子。 - thang
显示剩余2条评论
1个回答

19

大多数智能指针拥有它们所指向对象的所有权,即它们负责在适当的时候销毁该对象。然而,不同的智能指针具有不同的所有权语义。也就是说,它们告诉智能指针的用户如何转移或共享所有权,以及什么时候删除对象等信息。使用特定的智能指针描述了你对该对象所有权的意图。��有权可以转移到其他函数或对象。

boost::scoped_ptr 具有非常严格的所有权语义。它根本不允许任何所有权的转移。这是通过使其无法复制(因此无法通过值传递给另一个函数)来实现的。

另一个例子是 std::unique_ptr,它也相当严格。它的特殊能力是可以被移动。将一个 std::unique_ptr 作为右值传递给函数将允许该函数夺取对象的所有权。原始的 std::unique_ptr 立即失去所有权。这确保了所有权只由一个 std::unique_ptr 持有。

C++11 中与 boost::scoped_ptr 等价的是 const std::unique_ptr。这是因为将其声明为 const 会阻止任何移动,因此所有权无法转移。

理解所有权语义的重要性的一种简单方法是通过一个例子。假设你在使用一个恶意开发者的库,并且它有一个你不知道实现的函数,例如:

cat* foo();

你知道这个函数返回一个指向cat的指针。然而,它是一个裸指针。你不知道是否应该在某个时候销毁猫(使用delete),或者库是否会为你销毁它。你甚至不知道对象是否实际上是动态分配的。你也不知道库是否仍然保留着这只cat。过去,如果有这样的函数,你需要查看文档才能了解该怎么做。然而,现在我们有了智能指针,除了裸指针之外,裸指针有了自己的所有权语义- 最放松的语义。它说:“你最好相信我,在你传递它的整个生命周期中,我会保持这个cat有效,但我会管理它。不要保存太久。”

然而,一个聪明和善良的库开发人员现在会这样编写这个函数:

std::unique_ptr<cat> foo();

那么这有什么帮助呢?嗯,std::unique_ptr 告诉了你很多信息。它告诉你函数正在将对 cat 对象的所有权转让给你。现在,cat 就是你唯一的责任了。使用智能指针非常有帮助,因为你不需要考虑如何释放内存,只需使用指针,当它超出作用域时,对象就会被销毁。或者,如果你愿意,也可以将所有权转移给 另一个 函数。

这并不意味着只有一个指针会拥有 cat 的所有权。作为自豪的新主人,由你决定接下来发生什么。你完全可以决定要开始分享你的 cat 的所有权:

std::unique_ptr<cat> up = foo();
std::shared_ptr<cat> sp(up.release());
智慧和善良的foo库开发者只告诉了你她的意图。她给了你这只cat,现在你是它的拥有者。现在,你可以提供自己的所有权语义。
这样,一个boost::scoped_ptr就像一个贪婪的cat囤积者,永远不会与任何人分享这只cat,也不会把它交给任何人,将一直保留到他们离开这个世界的那天。

那解决了很多问题 :) 非常感谢! - SandBag_1996

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接