我将多个XML文件加载到QDomDocument
中,然后使用QMap
将标识字符串与每个文档相关联。我应该在地图中存储QDomDocument
还是指向QDomDocument
的指针?即,以下哪个示例更符合Qt最佳设计规范。
我怀疑示例A是首选。我看到的所有代码示例仅在堆栈上创建了本地QDomDocument
。并且,sizeof( QDomDocument )
是4个字节;因此,QDomDocument
可能是一个薄包装纸,可以对其进行浅表复制,而不会影响性能。
QDomDocument
个实例class Core
{
private:
QMap<QString, QDomDocument> docs;
public:
Core( void )
{
QFile file( "alpha.xml" );
file.open( QIODevice::ReadOnly );
QDomDocument doc;
doc.setContent( &file );
docs["alpha"] = doc;
// ... etc for other XML files
}
QString findThing( QString const & docName, QString const & thingName )
{
QDomDocument doc = docs[docName];
// ... search the doc for the thing with the given name
}
};
QDomDocument
实例的指针class Core
{
private:
QMap<QString, QDomDocument *> docs;
public:
Core( void )
{
QFile file( "alpha.xml" );
file.open( QIODevice::ReadOnly );
QDomDocument * pDoc = new QDomDocument();
pDoc->setContent( &file );
docs["alpha"] = pDoc;
// ... etc for other XML files
}
QString findThing( QString const & docName, QString const & thingName )
{
QDomDocument * pDoc = docs[docName];
// ... search the doc for the thing with the given name
}
};
OP的怀疑是正确的:QDomDocument
通过其基类QDomNode
持有一个指向其实现(PIMPL)的指针。
虽然fonZ正确地说原始对象将超出范围并被破坏,但是存储在映射中的副本将使(共享)实现保持活动状态。看一下the source,我们看到了QDomDocument
的空析构函数,它的基类析构函数揭示了一种引用计数机制:
QDomNode::~QDomNode()
{
if (impl && !impl->ref.deref())
delete impl;
}
在复制结构中,计数增加:
QDomNode::QDomNode(const QDomNode &n)
{
impl = n.impl;
if (impl)
impl->ref.ref();
}
以及任务:
QDomNode& QDomNode::operator=(const QDomNode &n)
{
if (n.impl)
n.impl->ref.ref();
if (impl && !impl->ref.deref())
delete impl;
impl = n.impl;
return *this;
}
因此方法A是合法和安全的,并且不涉及内存处理问题。
我还要指出,使用QMap::insert
代替下标运算符的性能更高。
否则:
QDomDocument doc;
doc.setContent( &file );
docs["alpha"] = doc;
或
docs["alpha"] = QDomDocument();
docs["alpha"].setContent( &file );
都会产生这个:
QDomDocument
对象(第二个片段中的一个临时对象)QDomDocument
对象,调用docs["alpha"]
使用中
docs.insert("alpha", QDomDocument());
docs["alpha"].setContent( &file );
将仅调用临时构造函数和地图项copy-constructor。
很明显,作用域结束时您的QDomDocument被删除:
{ // scope starts here
// create document on the stack
QDomDocument doc;
...
docs["alpha"] = doc;
} // scope ends here, stack is cleaned, doc is deleted
在堆上创建QDomDocument可以解决问题,但可能不是最佳解决方案。例如,这也可以正常工作:
{
...
docs["alpha"] = QDomDocument();
docs["alpha"].setContent( &file );
...
}