3

我正在浏览使用这么多 shared_ptrs 的替代方法,并在评论部分找到了一个很好的回复:

你真的需要共享所有权吗?如果您停下来思考几分钟,我相信您可以确定该对象的一个​​所有者,以及它的许多用户,他们只会在所有者的一生中使用它。因此,只需使其成为所有者的本地/成员对象,并将引用传递给需要使用它的人。

我很想这样做,但问题是拥有对象的定义现在需要首先完全定义拥有的对象。例如,假设我在 FooManager.h 中有以下内容:

class Foo; 
class FooManager
{
    shared_ptr<Foo> foo;
    shared_ptr<Foo> getFoo() { return foo; }
};

现在,根据上面的建议,FooManager.h 变为:

#include "Foo.h"
class FooManager
{
    Foo foo;
    Foo& getFoo() { return foo; }
};

我有两个问题。首先,FooManager.h 不再是轻量级的。每个包含它的 cpp 文件现在也需要编译 Foo.h。其次,我不再可以选择何时初始化 foo。它必须与 FooManager 同时初始化。我该如何解决这些问题?

4

3 回答 3

3

如果您不需要 的共享所有权语义shared_ptr,请考虑使用不同的智能指针容器。

对于您给出的示例(一个具有所有权且没有所有权转让的对象),boost::scoped_ptr将是一个不错的选择。

如果你不想使用 Boost,scoped_ptr它很容易实现——它在 Boost 文档中有很好的描述,它的实现(在 boost/shared_ptr.hpp 中)很简单。

于 2010-03-25T02:07:06.043 回答
3

您可以使用shared_ptr(或任何智能指针,甚至是哑指针)但没有共享所有权。

例如

class Foo; 
class FooManager
{
  private:
    shared_ptr<Foo> foo;
  public:
    Foo& getFoo() { return *foo; }
};

(这只是一个草图——你仍然需要一个 setFoo(),也许 getFoo() 应该返回一个 Foo *。但关键是你回到了轻量级,你可以控制何时创建 foo。)

于 2010-03-25T02:11:07.463 回答
2

使用 pimpl 成语,并停止内联这么多。

FooManager.h:

class Foo;

class FooManager
{
   struct Impl;
   Impl *m_impl;
public:
   Foo& getFoo();

   FooManager();
   ~FooManager();
};

FooManager.cpp

#include "Foo.h"
#include "FooManager.h"

struct FooManager::Impl
{
   Foo* m_foo;
   int m_someothermember;
   FooManager::Impl() : m_foo(NULL), m_someothermember(0) {}
};

FooManager::FooManager() : m_impl(new FooManager::Impl())
{}

Foo& FooManager::getFoo()
{
   // Lazy initialization
   if( !m_impl->m_foo ) {
      m_impl->m_foo = new Foo;
   }
   return *m_impl->m_foo;
 }

 FooManager::~FooManager()
 {
    delete m_impl->m_foo;
    delete m_impl;
 }

由于您已经在使用 boost,我建议您scoped_ptr在实际代码中使用它来实现它,而不是像我在本示例中所做的那样手动管理内存。要记住的重要一点是,前向声明对引用的作用与对指针的作用一样好(这是它起作用的部分原因shared_ptr)。

于 2010-03-25T02:25:01.430 回答