C++ 如何使用引用、避免标头膨胀和延迟初始化?
我正在浏览一个替代使用这么多共享的PTR的方法,并在评论部分找到了一个很好的回复: 你真的需要共享所有权吗? 如果你停下来想一想 分钟,我相信你能找到一个 对象的所有者,以及 它的用户,将永远只使用 它将在所有者的有生之年进行。所以 只需将其设置为本地/成员对象 并将引用传递给 那些需要使用它的人 我很想这样做,但问题是拥有对象的定义现在需要首先完全定义拥有对象。例如,假设我在FooManager.h中有以下内容:C++ 如何使用引用、避免标头膨胀和延迟初始化?,c++,initialization,reference,header-files,smart-pointers,C++,Initialization,Reference,Header Files,Smart Pointers,我正在浏览一个替代使用这么多共享的PTR的方法,并在评论部分找到了一个很好的回复: 你真的需要共享所有权吗? 如果你停下来想一想 分钟,我相信你能找到一个 对象的所有者,以及 它的用户,将永远只使用 它将在所有者的有生之年进行。所以 只需将其设置为本地/成员对象 并将引用传递给 那些需要使用它的人 我很想这样做,但问题是拥有对象的定义现在需要首先完全定义拥有对象。例如,假设我在FooManager.h中有以下内容: class Foo; class FooManager { share
class Foo;
class FooManager
{
shared_ptr<Foo> foo;
shared_ptr<Foo> getFoo() { return foo; }
};
class Foo;
class FooManager
{
struct Impl;
Impl *m_impl;
public:
Foo& getFoo();
FooManager();
~FooManager();
};
我有两个问题。首先,FooManager.h不再是轻量级的。包括它的每个cpp文件现在也需要编译Foo.h。第二,我不再需要选择何时初始化foo。它必须与FooManager同时初始化。如何解决这些问题? < P>如果您不需要共享代码所有权的代码> SydDypTr>/Cult>,请考虑使用不同的智能指针容器。 根据您给出的示例(一个对象拥有所有权,但没有所有权转让),
boost::scoped_ptr
将是一个不错的选择
如果您不想使用Boost,
作用域ptr
非常容易实现——Boost文档中对其进行了详细描述,它的实现(在Boost/shared_ptr.hpp中)非常简单。您可以使用共享_ptr
(或任何智能指针,甚至哑指针),但不具有共享所有权
例如
Foo类;
班级经理
{
私人:
共享_ptr foo;
公众:
Foo&getFoo(){return*Foo;}
};
(这只是一个草图-您仍然需要一个setFoo(),也许getFoo()应该返回一个Foo*。但问题是,您又回到了轻量级,您可以控制Foo的创建时间。)使用pimpl习惯用法,停止过多内联 FooManager.h:
class Foo;
class FooManager
{
shared_ptr<Foo> foo;
shared_ptr<Foo> getFoo() { return foo; }
};
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,我建议您在实际代码中使用
范围化的\u ptr
来实现这一点,而不是像我在本例中所做的那样手动管理内存。需要记住的重要一点是,前向声明对于引用和指针的效果一样好(这也是它用于共享\u ptr
的部分原因)。是的,对于boost:scoped \u ptr
的作业。无论何时通过无效重置(T*p=0)设置它;//从不抛出@BillyONeal:没错:它会抑制隐式复制构造函数和赋值运算符,但不会阻止您实现用户定义的复制构造函数和赋值运算符。但是,如果您不需要共享所有权,这可能不会是一个大问题。我要补充的是,在这种情况下,auto_ptr具有灵活性和简单性的最佳组合,因为他不再需要引用计数功能。auto_ptr不是因为“有些奇怪”而很难正确使用吗复制语义?pimpl习惯用法对解决方案至关重要吗?与头文件中的scoped_ptr m_foo
(甚至只是foo*m_foo)和foo&getFoo(){if(!m_foo)m_foo.reset(new foo);在cpp文件中返回*m_foo}
相比,相关的优势是什么?不是。pimpl习惯用法是针对“reduceheaderbloat”方面的,您不需要走这么远。