我可以使用boost :: make_shared和一个私有构造函数吗?
考虑以下几点:我可以使用boost :: make_shared和一个私有构造函数吗?
class DirectoryIterator;
namespace detail {
class FileDataProxy;
class DirectoryIteratorImpl
{
friend class DirectoryIterator;
friend class FileDataProxy;
WIN32_FIND_DATAW currentData;
HANDLE hFind;
std::wstring root;
DirectoryIteratorImpl();
explicit DirectoryIteratorImpl(const std::wstring& pathSpec);
void increment();
bool equal(const DirectoryIteratorImpl& other) const;
public:
~DirectoryIteratorImpl() {};
};
class FileDataProxy //Serves as a proxy to the WIN32_FIND_DATA struture inside the iterator.
{
friend class DirectoryIterator;
boost::shared_ptr<DirectoryIteratorImpl> iteratorSource;
FileDataProxy(boost::shared_ptr<DirectoryIteratorImpl> parent) : iteratorSource(parent) {};
public:
std::wstring GetFolderPath() const {
return iteratorSource->root;
}
};
}
class DirectoryIterator : public boost::iterator_facade<DirectoryIterator, detail::FileDataProxy, std::input_iterator_tag>
{
friend class boost::iterator_core_access;
boost::shared_ptr<detail::DirectoryIteratorImpl> impl;
void increment() {
impl->increment();
};
bool equal(const DirectoryIterator& other) const {
return impl->equal(*other.impl);
};
detail::FileDataProxy dereference() const {
return detail::FileDataProxy(impl);
};
public:
DirectoryIterator() {
impl = boost::make_shared<detail::DirectoryIteratorImpl>();
};
};
好像DirectoryIterator应该能够调用boost::make_shared<DirectoryIteratorImpl>
,因为它是DirectoryIteratorImpl
的朋友。但是,此代码无法编译,因为DirectoryIteratorImpl的构造函数是私有的。
因为此类是一个内部实现细节的DirectoryIterator
客户不应该碰,这将是很好,如果我能保持构造私有。
这是我对make_shared
的基本误解,还是我需要标记某种提升块作为friend
以便调用编译?
你确实需要做一些提升作品的朋友这一点。基本上make_shared
正在调用构造函数,并且这是从朋友函数内部完成的事实,对编译器无关紧要。
好消息是,虽然make_shared
被调用构造函数,而不是其他任何作品。所以只是让make_shared
朋友会工作......然而,这意味着任何人都可以再创建一个shared_ptr<DirectoryIteratorImpl>
...
嗯...这是讨厌的地狱:)谢谢! – 2010-04-07 13:32:20
'make_shared'的问题是它分配了一块内存,然后使用放置'new',这就是为什么它必须自己调用构造函数。我同意你的问题很烦人。 – 2010-04-07 13:59:35
这样做的问题是,如果您迁移到TR1或C++ 0x,或者即使增强版发布更新,也无法保证它仍能正常工作。 – dvide 2010-04-07 17:19:32
是否有一个很好的理由不使用好老shared_ptr
构造? (如果有一个,你可能想看看make_shared
实现做)
DirectoryIterator()
: impl(new detail::DirectoryIteratorImpl())
{}
这样调用构造函数从DirectoryIterator
类所做的已经是DirectoryIteratorImpl
的朋友不开放所有其他代码的大门。
不,它没有任何问题。但我被告知使用'make_shared'在http://stackoverflow.com/questions/2569046/is-there-a-way-to-increase-the-efficiency-of-shared-ptr-by-storing-the-参考/ 2569211#2569211。我现在所做的只是按照你的建议完成。 +1 – 2010-04-07 13:31:16
'make_shared'在其内存分配方面效率更高......(更少碎片化,更高速度) – 2010-04-07 13:58:21
我知道内存碎片(你应该真的测量一下),但我有时会读到(实际上是在这里):*他谁牺牲正确的表现不值得*,这是一个很好的座右铭。而在最初的相关问题中,比利承认他不需要表演。如果构造函数是私有的,'make_shared'不应该是朋友(通过允许任何人通过'make_shared'构造对象来打破封装) – 2010-04-07 15:06:31
您可以将类分成接口部分和实现部分。 接口部分公开,实现部分可以有公共构造函数。 但是,这意味着你必须使用虚拟继承。
你确定你需要shared_ptr的为您实现了一套指针? boost :: scoped_ptr通常更合适,使事情变得更简单。如果您希望DirectoryIterator是可复制的,并且副本应共享单个impl实例,则通常只会在此情况下使用Shared_ptr。在您发布的代码中,似乎共享impl的副本将是一个错误。 Shared_ptr用于多个指针应共享实例的所有权。 – Alan 2010-04-08 16:17:44