我正在浏览使用这么多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同时初始化。我如何解决这些问题?
答案 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
起作用的部分原因)。