我将加载多个XML文件,每个文件到QDomDocument中,然后使用QMap将标识字符串与每个文档相关联。我应该在 map 中存储QDomDocument还是指向QDomDocument的指针?即,以下哪个示例更符合Qt最佳设计规范。

我怀疑首选示例A。我看到的所有代码示例仅在堆栈上创建了一个本地QDomDocument。并且,sizeof( QDomDocument )是4个字节;因此,QDomDocument可能是一个很薄的包装程序,可以对其进行浅拷贝而不会影响性能。

答: map 包含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
  }
};

B. Map包含指向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说的很正确,即原始对象将超出范围并被破坏,但存储在映射中的副本将使(共享)实现保持 Activity 状态。看一看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对象(在第二个片段中是一个临时的)
  • (在 map 内部)创建了另一个QDomDocument对象,调用docs["alpha"]
  • 将后者分配给第一个。

  • 使用
    docs.insert("alpha", QDomDocument());
    docs["alpha"].setContent( &file );
    

    将仅调用临时构造函数和 map 项copy-constructor。

    关于c++ - 我应该在堆上创建一个新的QDomDocument吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58101063/

    10-10 17:53