如何使用引用,避免标题膨胀和延迟初始化?

时间:2010-03-25 02:01:36

标签: c++ initialization reference header-files smart-pointers

我正在浏览使用这么多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同时初始化。我如何解决这些问题?

3 个答案:

答案 0 :(得分:3)

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

根据您提供的示例(一个对象拥有所有权而不转让所有权),boost::scoped_ptr将是一个不错的选择。

如果您不想使用Boost,scoped_ptr非常容易实现 - 它在Boost文档中有详细描述,其实现(在boost / shared_ptr.hpp中)非常简单。

答案 1 :(得分:3)

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

E.g。

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

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

答案 2 :(得分: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起作用的部分原因)。

相关问题