递归创建 boost 属性 树
Creating a boost property tree recursively
我正在尝试从已有的树结构中创建一个提升 属性 树。我在 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;
}
ptree children;
是局部变量,方法return时内存不再有效。将其更改为 ptree &children = *(new ptree());
。但使用后需要注意删除。如果你的方法 return 是普通的 ptree
而不是 'pointer to ptree
' 会更安全。在这种情况下,您无需担心 new
或 delete
.
最严重的违规者是
- 返回指向本地的悬垂指针
ptree
这一行:
std::shared_ptr<ITreeNode> c(child); // cast raw pointer to shared pointer
这不是演员表。它是一个转换构造函数。通过调用它,您 转让所有权 。这直接意味着你的循环 delete 原始 ITreeNode
树中的所有 children (因为当 c
被破坏时,它隐含地 [= =18=] 因为没有其他人持有共享指针)。
我正在简化代码。待会儿post
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;
}
完整演示
#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>
我正在尝试从已有的树结构中创建一个提升 属性 树。我在 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;
}
ptree children;
是局部变量,方法return时内存不再有效。将其更改为 ptree &children = *(new ptree());
。但使用后需要注意删除。如果你的方法 return 是普通的 ptree
而不是 'pointer to ptree
' 会更安全。在这种情况下,您无需担心 new
或 delete
.
最严重的违规者是
- 返回指向本地的悬垂指针
ptree
这一行:
std::shared_ptr<ITreeNode> c(child); // cast raw pointer to shared pointer
这不是演员表。它是一个转换构造函数。通过调用它,您 转让所有权 。这直接意味着你的循环 delete 原始
ITreeNode
树中的所有 children (因为当c
被破坏时,它隐含地 [= =18=] 因为没有其他人持有共享指针)。
我正在简化代码。待会儿post
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;
}
完整演示
#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>