c++ - 递归创建 boost 属性树

标签 c++ boost boost-propertytree

我正在尝试从已有的树结构创建一个 boost 属性树。我在 ptree node = *p 行上收到内存访问冲突错误。

我应该如何更改此代码才能使其正常工作?

ptree* WebTreeView::insertProjectNode(std::shared_ptr<ITreeNode> projectNode)
{

if (projectNode->Children().size() == 0)
{
    return nullptr;
}

ptree children;

for (auto child : projectNode->Children())
{
    std::shared_ptr<ITreeNode> c(child); // cast raw pointer to shared pointer
    std::string nodetext = c->Name().c_str();

    ptree *p = insertProjectNode(c);

    if (p)
    {
        ptree node = *p; 
        children.put_child(nodetext, node);
    }
    else
    {
        children.put(nodetext, " ");
    }
}

return &children;
}

最佳答案

最严重的罪犯是

  1. 返回一个指向本地ptree的悬空指针
  2. 这一行:

    std::shared_ptr<ITreeNode> c(child); // cast raw pointer to shared pointer
    

    这不是类型转换。它是一个转换构造函数。通过调用它,您转让所有权。这直接意味着您的循环删除原始ITreeNode树中的所有子节点(因为当c被破坏时,它隐式地执行 >删除子进程,因为没有其他人持有共享指针)。

我正在简化代码。稍后会发布。

void WebTreeView::insertProjectNode(ITreeNode const& node, ptree& into) {
    ptree current;

    for (auto const* child : node.Children())
        if (child) insertProjectNode(*child, current);

    into.add_child(node.Name(), current);
}

或者,更接近您的界面(但缺少命名根的步骤:)

ptree WebTreeView::insertProjectNode(ITreeNode const& node) {
    ptree current;

    for (auto const* child : node.Children())
        if (child) 
            current.add_child(child->Name(), insertProjectNode(*child));

    return current;
}

完整演示

Live On Coliru

#include <boost/property_tree/ptree.hpp>
#include <memory>
#include <iostream>
#include <list>

struct ITreeNode {
    std::string Name() const { return _name; }
    std::list<ITreeNode *> const &Children() const { return _children; }

    ITreeNode(ITreeNode const&)            = delete;
    ITreeNode& operator=(ITreeNode const&) = delete;

    ITreeNode(std::string name = "", std::list<ITreeNode*> const& children = {})
        : _name(std::move(name)),
          _children(children)
    {
    }

    ~ITreeNode() {
        for (auto* c : _children)
            delete c; // TODO make depthfirst deletion using iteration instead
                      // of breadth-first using recursion to avoid
                      // stack-overflow on large trees
    }
  private:
    std::string _name;
    std::list<ITreeNode *> _children;
};

using boost::property_tree::ptree;

namespace demo {
    ptree insertProjectNode(ITreeNode const& node);

    ptree insertProjectNode(ITreeNode const& node) {
        ptree current;

        for (auto const* child : node.Children())
            if (child) 
                current.add_child(child->Name(), insertProjectNode(*child));

        return current;
    }
}

#include <boost/property_tree/xml_parser.hpp>

int main() {

    ITreeNode const source = { "a", {
        new ITreeNode { "ab", {
            new ITreeNode { "ab0" },
            new ITreeNode { "ab1" },
            new ITreeNode { "ab2" },
        } },
        new ITreeNode { "ac", {
            new ITreeNode { "ac0" },
        } },
        new ITreeNode { "ad", {
            new ITreeNode { "ad0" },
            new ITreeNode { "ad1" },
            new ITreeNode { "ad2" },
            new ITreeNode { "ad3" },
        } },
    } };

    ptree root;
    root.add_child(source.Name(), demo::insertProjectNode(source));

    boost::property_tree::write_xml(std::cout, root,
            boost::property_tree::xml_writer_make_settings<std::string>(' ', 2));
}

打印

<?xml version="1.0" encoding="utf-8"?>
<a>
  <ab>
    <ab0/>
    <ab1/>
    <ab2/>
  </ab>
  <ac>
    <ac0/>
  </ac>
  <ad>
    <ad0/>
    <ad1/>
    <ad2/>
    <ad3/>
  </ad>
</a>

关于c++ - 递归创建 boost 属性树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29521533/

相关文章:

c++ - 如何在没有等待结果的情况下触发内部循环异步任务

c++ - BOOST::CRC使用process.block()方法创建校验和

C++ 添加用于序列化 vector 对的自定义 XML 标记

c++ - 如何合并/更新 boost::property_tree::ptree?

c++ - 打印 boost 属性树生成的 xml

c++ - 超越结构的一个元素以查看另一个元素是否合法?

c++ - 使用 PostMessage 将文本发送到非事件窗口虽然无法发送类次

c++ - 在 Qt 中使用仅 header 库管理项目

c++ - Boost boyer_moore 搜索语料库类型的示例类?

c++ - 如何迭代 boost::property_tree 中的 XML 结构